home *** CD-ROM | disk | FTP | other *** search
- /*
-
- MDI Frame window handler
-
- */
-
- #include "netfone.h"
-
- // Variables exported
-
- HWAVEOUT hWaveOut = NULL; // Wave output handle
- HWAVEIN hWaveIn = NULL; // Wave input handle
- int outputActive = FALSE; // Is wave output open ?
- int inputActive = FALSE; // Is wave input open ?
- int openConnections = 0; // Number of open connections
- int listeners = 0; // Current wantsInput windows
- int broadcasting = FALSE; // Broadcasting to all connections ?
- static int outputTimeout = 0; // Output release timeout
- long outputPending = 0; // Output buffers in queue
- int halfDuplexTransition = FALSE; // Transitioning from output to input ?
- int outputInShutdown = FALSE; // Close output when last buffer returned
- gsm gsmh = NULL; // GSM handle
- HCURSOR phoneCursor = NULL,
- earCursor = NULL; // Cursors
- int compression = FALSE; // 2X compression mode
- int gsmcompress = TRUE; // GSM compression mode
- int adpcmcompress = FALSE; // ADPCM compression mode
- int lpccompress = FALSE; // LPC compression mode
-
- int modemEnable = FALSE; // Modem connections enabled ?
- char modemInitString[128] = // Modem initialisation string
- "ATQ0V1E1S0=1";
- char baudrate[12] = "19200"; // Baud rate
- char commport[12] = "COM1"; // Communications port
- int modemShowRant = TRUE; // Show rant about Windows serial I/O support
- int modemSessions = 0; // Open sessions on modem
-
- int alwaysBindSocket = FALSE; // Bind output socket (WINSOCK bug work-around)
- int useSendNotSendto = FALSE; // Use send() to socket, not sendto()
- int waNetNoConnect = FALSE; // Don't connect(), use sendto()
- int waNetUseSend = FALSE; // Use send(), not sendto() always
- int waNetMultiTTLisChar = FALSE; // Argument to IP_MULTICAST_TTL setsockopt is char
- int waAudioHalf = FALSE; // Assume audio half-duplex; don't test
- int waAudio11025 = FALSE; // Assume audio 11025 samples/sec
-
- int halfDuplex = FALSE; // Audio hardware is half-duplex
- static int audioIs8Bit = FALSE; // Nonzero if audio is 8 bit only
- static int audioUse8Bit = FALSE; // Use 8 bit audio
- int netMaxSamples; // Maximum samples network can send
- static int currentInputLength; // Current expected input buffer length
- int currentInputSamples; // Samples desired in current input buffers
- int holped = FALSE; // Help was invoked somewhere
- static char ringFileName[MAX_PATH] = "";// Ring file name
- static int lookWho_sTalking = FALSE; // Restore from icon on new connection
-
- char lwl_s_server[MAX_PATH]; // Look Who's Listening server name
- char lwl_s_email[80]; // E-mail address
- char lwl_s_fullname[80]; // Full name
- char lwl_s_phone[80]; // Telephone number
- char lwl_s_location[80]; // Location name
- int lwl_s_publish; // Publish in directory ?
- int lwl_s_exact; // Exact match only ?
-
- char lwl_a_server[MAX_PATH]; // Look Who's Listening query server
- int lwl_a_exact; // Exact matches only
-
- int lwl_t_published = FALSE; // Directory listing published
- int lwl_t_resend = 0; // Time to update directory listing ?
- int lwl_t_diactive = FALSE; // LWL dialogue up
-
- unsigned long ssrc; // RTP synchronisation source identifier
- unsigned long timestamp; // RTP packet timestamp
- unsigned short seq; // RTP packet sequence number
- char *sdes = NULL; // RTP SDES packet
- int sdesl; // RTP SDES packet length
-
- HINSTANCE hInst; // The current instance handle
- HACCEL hAccel; // Accelerator table handle
- HWND hwndMDIFrame; // MDI frame window handle
- HWND hwndMDIClient; // MDI client window handle
- HWND hDlgPropeller = NULL; // Propeller head modeless dialogue
- FARPROC pfnPropeller = NULL; // Propeller head procedure instance
- LPSTR commandLine = NULL; // Command line from invocation
- HWND hDlgAnswer = NULL; // Answering machine modeless dialogue
- FARPROC pfnAnswer = NULL; // Answering machine procedure instance
- LPSTR pszAppName; // Application name
- INT tmAveCharWidth; // TEXTMETRIC.tmAveCharWidth
- INT tmHeight; // TEXTMETRIC.tmHeight
-
- int rememberedConnections = 0; // Number of remembered connections
- LPSTR rememberedConnection[REMEMBER_CONNECTIONS]; // Remembered connections
-
- UINT fileOpenHelpButton; // File open help button message value
- char *fileHelpKey = NULL; // Help key for file open/save in progress
-
- int multiMemberships = 0; // Number of multicast group memberships
- struct in_addr multiAddr[IP_MAX_MEMBERSHIPS]; // Multicast group IP numbers
- LPSTR multiName[IP_MAX_MEMBERSHIPS]; // Multicast group names
- int multiLoop = FALSE; // Multicast loop-back mode
- int multiBrainDead = FALSE; // Multicast loop-back option not supported
-
- // Local variables
-
- #define nWaveHeaders 4
- static SOCKET sCommand = INVALID_SOCKET; // Command socket
- static SOCKET lwlsock = INVALID_SOCKET; // Look Who's Listening periodic update socket
- static LPWAVEHDR inWaveHeader[nWaveHeaders];// Pointers to wave input buffers
- static int inputTerm = FALSE; // Input terminating
- static soundbuf receivedSoundBuffer; // Sound buffer from network
- static LPSTR modemSb = NULL; // Modem sound buffer assembly area
-
- static int audioChannels = 1; // Audio input channels
- static int samplesPerSecond = 8000; // Sound sampling rate
- static int bytesPerSecond = 16000; // Sample bytes per second
- static int sampleAlignment = 2; // Sample frame size
- static int bitsPerSample = 16; // Bits per sample
-
- static char kS0[] = "0", kS1[] = "1"; // Frequently used string constants
-
- // Export current audio settings to About dialogue
-
- int aboutInSamples = 0; // Input samples per second
- int aboutInBits; // Input bits per sample
- int aboutOutSamples = 0; // Output samples per second
- int aboutOutBits; // Output bits per sample
-
- // Export various status information to Propeller Head dialogue
-
- long packetsReceived = 0, // Network packet traffic counters
- packetsSent = 0,
- inputPacketsLost = 0, // Input packets lost due to half-duplex
- outputPacketsLost = 0; // Output packets lost due to net traffic
-
- int messageQueueSize = 120; // Inbound message queue size
-
- // Network properties
-
- int aboutUDPmax = 0; // Maximum UDP packet size
-
- // Private constants
-
- #define DESIRED_WINSOCK_VERSION 0x0101 // we'd like winsock ver 1.1...
- #define MINIMUM_WINSOCK_VERSION 0x0001 // ...but we'll take ver 1.0
-
- #define MODEM_INPUT_EVENT 9999 // Modem input socket status
-
- // MDI message forwarder
-
- static LRESULT Frame_MDIMessageForwarder(HWND hwnd, UINT nMessage,
- WPARAM wParam, LPARAM lParam)
- {
- return DefFrameProc(hwnd, hwndMDIClient, nMessage, wParam, lParam);
-
- }
-
- // PROPELLER -- Update propeller head dialogue if it's displayed.
-
- void propeller(int control, DWORD value)
- {
- if (hDlgPropeller != NULL) {
- char s[80];
-
- wsprintf(s, Format(0), value);
- SetDlgItemText(hDlgPropeller, control, s);
- }
- }
-
- /* FINDCLIENTBYHOST -- Find the connection window for a given
- host address. */
-
- static HWND findClientByHost(LPSOCKADDR_IN paddr)
- {
- HWND hwnd;
-
- hwnd = GetWindow(hwndMDIClient, GW_CHILD);
-
- while (hwnd != NULL) {
- if ((WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC) == ((WNDPROC) connectWndProc)) {
- LPCLIENT_DATA pClientData = CLIENTPTR(hwnd);
-
- if ((pClientData != NULL) &&
- (pClientData->inetSock.sin_addr.s_addr == paddr->sin_addr.s_addr)) {
- return hwnd;
- }
- }
- hwnd = GetWindow(hwnd, GW_HWNDNEXT);
- }
- return NULL;
- }
-
- /* GETACTIVECONNECTION -- Get the active connection window. If no
- connection is active, NULL is returned.
- A connection will not be returned unless
- it has a valid client data structure. */
-
- static HWND getActiveConnection(void)
- {
- LRESULT mdiActive;
- HWND hwnd;
-
- if (hwndMDIClient != NULL) {
- mdiActive = SendMessage(hwndMDIClient, WM_MDIGETACTIVE,
- 0, 0L);
- hwnd = (HWND) LOWORD(mdiActive);
- if (hwnd != NULL &&
- ((WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC) == ((WNDPROC) connectWndProc)) &&
- CLIENTPTR(hwnd) != NULL) {
- return hwnd;
- }
- }
- return NULL;
- }
-
- /* MULTICASTJOIN -- Join or drop multicast groups given in
- the multicast table. */
-
- void multicastJoin(HWND hwnd, int join)
- {
- int i, what;
- struct ip_mreq mreq;
-
- if (join) {
- int sstat;
- if (waNetMultiTTLisChar) {
- u_char loop;
-
- loop = (u_char) multiLoop;
- sstat = setsockopt(sCommand, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &loop,
- sizeof loop);
- } else {
- int loop;
-
- loop = (int) multiLoop;
- sstat = setsockopt(sCommand, IPPROTO_IP, IP_MULTICAST_LOOP, (char *) &loop,
- sizeof loop);
- }
- if (sstat == -1) {
- int serr = WSAGetLastError();
-
- if (serr == WSAENOPROTOOPT) {
- // Windows 95 and NT don't support IP_MULTICAST_LOOP
- multiBrainDead = TRUE;
- } else {
- /* Since many Winsock implementations don't support multicast,
- disable the warning to prevent a natter every time we start
- up. */
- #ifdef MULTICAST_WARNING
- MsgBox(hwnd, MB_ICONSTOP | MB_OK,
- Format(8),
- serr, SockerrToString(serr));
- #endif
- }
- }
- }
- what = join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP;
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- for (i = 0; i < multiMemberships; i++) {
- mreq.imr_multiaddr.s_addr = multiAddr[i].s_addr;
- if (setsockopt(sCommand, IPPROTO_IP, what,
- (char *) &mreq, sizeof mreq) == -1) {
- int serr = WSAGetLastError();
-
- MsgBox(hwnd, MB_ICONSTOP | MB_OK,
- Format(9),
- (LPSTR) (join ? Format(10) : Format(11)), inet_ntoa(multiAddr[i]),
- serr, SockerrToString(serr));
- }
- if (!what && multiName[i] != NULL) {
- GlobalFreePtr(multiName[i]);
- multiName[i] = NULL;
- }
- }
- }
-
- /* ISHALFDUPLEX -- Try to open audio input and output simultaneously.
- If it fails, mark the hardware half-duplex. */
-
- static int isHalfDuplex(HWND hwnd)
- {
- LPPCMWAVEFORMAT wf = NULL;
- WORD woo;
- int hdx = FALSE;
-
- if (waAudio11025) {
- samplesPerSecond = 11025;
- bytesPerSecond = samplesPerSecond * 2;
- }
-
- wf = (LPPCMWAVEFORMAT) GlobalAllocPtr(GPTR, sizeof(PCMWAVEFORMAT));
- if (wf == NULL) {
- MessageBox(hwnd, rstring(IDS_T_WAVE_IN_FORMAT_ERR),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- return -1;
- }
- wf->wf.wFormatTag = WAVE_FORMAT_PCM;
- wf->wf.nChannels = audioChannels;
-
- // Input initialisation
-
- while (TRUE) {
- wf->wf.nSamplesPerSec = samplesPerSecond;
- wf->wf.nAvgBytesPerSec = bytesPerSecond;
- wf->wf.nBlockAlign = sampleAlignment;
- wf->wBitsPerSample = bitsPerSample;
- woo = waveInOpen(&hWaveIn, (WORD) WAVE_MAPPER, (LPWAVEFORMAT) wf,
- 0L, 0L, WAVE_FORMAT_QUERY);
- if (bitsPerSample > 8 && woo == WAVERR_BADFORMAT) {
- audioIs8Bit = TRUE;
- }
-
- /* If our preferred mode (16 bit) isn't supported, try falling
- back to bottom-feeder 8 bit per sample mode. */
-
- if ((audioUse8Bit || woo == WAVERR_BADFORMAT) && (bitsPerSample > 8)) {
- bitsPerSample /= 2;
- sampleAlignment /= 2;
- bytesPerSecond /= 2;
- wf->wf.nAvgBytesPerSec = bytesPerSecond;
- wf->wf.nBlockAlign = sampleAlignment;
- wf->wBitsPerSample = bitsPerSample;
- woo = waveInOpen(&hWaveIn, (WORD) WAVE_MAPPER, (LPWAVEFORMAT) wf,
- 0L, 0L, WAVE_FORMAT_QUERY);
- }
-
- /* If we've failed to initialise in either 16 or 8 bit mode
- at 8000 samples per second, it's possible the sound card
- doesn't support any sampling mode below the Windows standard
- of 11025 samples per second. Have another go-round and see
- if 11025 works. */
-
- if (woo == WAVERR_BADFORMAT && samplesPerSecond == 8000) {
- samplesPerSecond = 11025;
- bitsPerSample = 16;
- sampleAlignment = bitsPerSample / 8;
- bytesPerSecond = samplesPerSecond * sampleAlignment;
- } else {
- break;
- }
- }
- if (woo != 0) {
- MessageBox(hwnd, rstring(IDS_T_WAVE_RECORD_FORMAT_ERR),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- GlobalFreePtr(wf);
- return -1;
- }
- if ((woo = waveInOpen(&hWaveIn, (UINT) WAVE_MAPPER,
- (LPWAVEFORMAT) wf, (DWORD) (UINT) hwnd, 0L, (DWORD) CALLBACK_WINDOW)) != 0) {
- char et[MAXERRORLENGTH];
-
- waveInGetErrorText(woo, et, sizeof et);
- MessageBox(hwnd, et, rstring(IDS_T_ERR_OPEN_WAVE_INPUT), MB_OK | MB_ICONEXCLAMATION);
- GlobalFreePtr(wf);
- return -1;
- }
- aboutInBits = bitsPerSample;
- aboutInSamples = samplesPerSecond;
-
- /* If workaround is set, close input now and mark half-duplex
- without waiting for the open of output to fail. */
-
- if (waAudioHalf) {
- waveInClose(hWaveIn);
- hdx = halfDuplex = TRUE;
- }
-
- // Output initialisation
-
- while (TRUE) {
- woo = waveOutOpen(&hWaveOut, (WORD) WAVE_MAPPER, (LPWAVEFORMAT) wf,
- 0L, 0L, WAVE_FORMAT_QUERY);
- if (bitsPerSample > 8 && woo == WAVERR_BADFORMAT) {
- audioIs8Bit = TRUE;
- }
-
- /* If our preferred mode (16 bit, 11025 samples/second) isn't
- supported, try falling back to bottom-feeder 8 bit per sample
- mode. */
-
- if ((audioUse8Bit || woo == WAVERR_BADFORMAT) && bitsPerSample > 8) {
- bitsPerSample /= 2;
- sampleAlignment /= 2;
- bytesPerSecond /= 2;
- wf->wf.nAvgBytesPerSec = bytesPerSecond;
- wf->wf.nBlockAlign = sampleAlignment;
- wf->wBitsPerSample = bitsPerSample;
- woo = waveOutOpen(&hWaveOut, (WORD) WAVE_MAPPER, (LPWAVEFORMAT) wf,
- 0L, 0L, WAVE_FORMAT_QUERY);
- }
-
- /* If we've failed to initialise in either 16 or 8 bit mode
- at 8000 samples per second, it's possible the sound card
- doesn't support any sampling mode below the Windows standard
- of 11025 samples per second. Have another go-round and see
- if 11025 works. */
-
- if (woo == WAVERR_BADFORMAT && samplesPerSecond == 8000) {
- samplesPerSecond = 11025;
- bitsPerSample = 16;
- sampleAlignment = bitsPerSample / 8;
- bytesPerSecond = samplesPerSecond * sampleAlignment;
- } else {
- break;
- }
- }
-
- if (woo != 0) {
- char et[MAXERRORLENGTH];
-
- waveOutGetErrorText(woo, et, sizeof et);
- MessageBox(hwnd, et, rstring(IDS_T_WAVE_PLAY_FORMAT_ERR),
- MB_OK | MB_ICONEXCLAMATION);
- GlobalFreePtr(wf);
- hdx = -1;
- goto FatalAudioExit;
- }
- if ((woo = waveOutOpen(&hWaveOut, (WORD) WAVE_MAPPER,
- (LPWAVEFORMAT) wf, (DWORD) (UINT) hwnd, 0, (DWORD) CALLBACK_WINDOW)) != 0) {
- char et[MAXERRORLENGTH];
-
- /* The next line looks wrong, doesn't it? But I've seen drivers
- for half-duplex sound boards that return NOTSUPPORTED instead
- of ALLOCATED when you try to open input and output at the
- same time. */
-
- if (!waAudioHalf && (woo == MMSYSERR_ALLOCATED || woo == MMSYSERR_NOTSUPPORTED)) {
- hdx = halfDuplex = TRUE;
- waveInClose(hWaveIn);
- if (waveOutOpen(&hWaveOut, (WORD) WAVE_MAPPER,
- (LPWAVEFORMAT) wf, (DWORD) (UINT) hwnd, 0,
- (DWORD) CALLBACK_WINDOW) == 0) {
- aboutOutBits = bitsPerSample;
- aboutOutSamples = samplesPerSecond;
- waveOutClose(hWaveOut);
- goto HdxAudioExit;
- }
- } else {
- waveOutGetErrorText(woo, et, sizeof et);
- MessageBox(hwnd, et, rstring(IDS_T_ERR_OPEN_WAVE_OUTPUT),
- MB_OK | MB_ICONEXCLAMATION);
- hdx = -1;
- }
- } else {
- aboutOutBits = bitsPerSample;
- aboutOutSamples = samplesPerSecond;
- waveOutClose(hWaveOut);
- }
-
- FatalAudioExit:
- if (!waAudioHalf) {
- waveInClose(hWaveIn);
- }
- HdxAudioExit:
- GlobalFreePtr(wf);
- return hdx;
- }
-
- /* WAVEOUTSHUTDOWN -- Shutdown wave audio output, if open. */
-
- static void waveOutShutdown(void)
- {
- if (outputActive) {
- V waveOutReset(hWaveOut);
- if (outputPending) {
- outputInShutdown = TRUE;
- propUpdateAudio();
- } else {
- V waveOutClose(hWaveOut);
- outputActive = FALSE;
- propUpdateAudio();
- }
- }
- }
- /* INPUTSAMPLECOUNT -- Calculate best sample count for an audio input
- buffer based on the current compression
- modes and the characteristics of the audio
- hardware. */
-
- int inputSampleCount(void)
- {
- int l = lpccompress ? (compression ? 3600 : 1800) :
- (gsmcompress ?
- (compression ? 3200 : 1600) :
- ((512 - (sizeof(soundbuf) - BUFL)) * (compression ? 2 : 1)));
- if (adpcmcompress) {
- l *= 2;
- l -= 4; // Leave room for state at the end
- }
- return l;
- }
-
- /* INPUTBUFFERLENGTH -- Calculate best length in bytes for an audio input
- buffer based on the current compression
- modes and the characteristics of the audio
- hardware. */
-
- static int inputBufferLength(void)
- {
- return (bitsPerSample / 8) * inputSampleCount();
- }
-
- /* STARTWAVEINPUT -- Activate wave audio input. Returns TRUE
- if successful, FALSE if no input will be
- forthcoming for some twiddley reason or
- another. The window handle is simply used
- as the parent for the message boxes announcing
- the bad news. */
-
- int startWaveInput(HWND hwnd)
- {
- // Attempt to initialise the audio input port
-
- if (!inputActive) {
- int i;
- LPPCMWAVEFORMAT wf;
- WORD woo;
-
- wf = (LPPCMWAVEFORMAT) GlobalAllocPtr(GPTR, sizeof(PCMWAVEFORMAT));
- if (wf == NULL) {
- MessageBox(hwnd, rstring(IDS_T_WAVE_IN_FORMAT_ERR),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- }
- wf->wf.wFormatTag = WAVE_FORMAT_PCM;
- wf->wf.nChannels = audioChannels;
-
- while (TRUE) {
- wf->wf.nSamplesPerSec = samplesPerSecond;
- wf->wf.nAvgBytesPerSec = bytesPerSecond;
- wf->wf.nBlockAlign = sampleAlignment;
- wf->wBitsPerSample = bitsPerSample;
- woo = waveInOpen(&hWaveIn, (WORD) WAVE_MAPPER, (LPWAVEFORMAT) wf,
- 0L, 0L, WAVE_FORMAT_QUERY);
- if (bitsPerSample > 8 && woo == WAVERR_BADFORMAT) {
- audioIs8Bit = TRUE;
- }
-
- /* If our preferred mode (16 bit) isn't supported, try falling
- back to bottom-feeder 8 bit per sample mode. */
-
- if ((audioUse8Bit || woo == WAVERR_BADFORMAT) && (bitsPerSample > 8)) {
- bitsPerSample /= 2;
- sampleAlignment /= 2;
- bytesPerSecond /= 2;
- wf->wf.nAvgBytesPerSec = bytesPerSecond;
- wf->wf.nBlockAlign = sampleAlignment;
- wf->wBitsPerSample = bitsPerSample;
- woo = waveInOpen(&hWaveIn, (WORD) WAVE_MAPPER, (LPWAVEFORMAT) wf,
- 0L, 0L, WAVE_FORMAT_QUERY);
- }
-
- /* If we've failed to initialise in either 16 or 8 bit mode
- at 8000 samples per second, it's possible the sound card
- doesn't support any sampling mode below the Windows standard
- of 11025 samples per second. Have another go-round and see
- if 11025 works. */
-
- if (woo == WAVERR_BADFORMAT && samplesPerSecond == 8000) {
- samplesPerSecond = 11025;
- bitsPerSample = 16;
- sampleAlignment = bitsPerSample / 8;
- bytesPerSecond = samplesPerSecond * sampleAlignment;
- } else {
- break;
- }
- }
- if (woo != 0) {
- MessageBox(hwnd, rstring(IDS_T_WAVE_RECORD_FORMAT_ERR),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- GlobalFreePtr(wf);
- return FALSE;
- }
- for (i = 0; i < 2; i++) {
- if ((woo = waveInOpen(&hWaveIn, (UINT) WAVE_MAPPER,
- (LPWAVEFORMAT) wf, (DWORD) (UINT) hwndMDIFrame, 0L, (DWORD) CALLBACK_WINDOW)) != 0) {
- char et[MAXERRORLENGTH];
-
-
- /* The next line looks wrong, doesn't it? But I've seen drivers
- for half-duplex sound boards that return NOTSUPPORTED instead
- of ALLOCATED when you try to open input and output at the
- same time. */
-
- if (i == 0 && outputActive && (woo == MMSYSERR_ALLOCATED ||
- woo == MMSYSERR_NOTSUPPORTED)) {
-
- /* Okay, the preponderance of evidence points at our
- machine being burdened with a half-duplex audio
- device--one where the fact that we're playing audio
- prevents from from simultaneously receiving it.
- This is bad. Let's proceed as we'd have done on
- the 80 metre band in 1935--mute the receiver and
- blast on our carrier regardless. */
-
- V waveOutReset(hWaveOut);
- halfDuplex = TRUE; // Indicate wave output swiped
- if (outputPending) {
- halfDuplexTransition = TRUE;
- GlobalFreePtr(wf);
- propUpdateAudio();
- return TRUE;
- } else {
- V waveOutClose(hWaveOut);
- outputActive = FALSE;
- propUpdateAudio();
- }
- continue;
- }
- waveInGetErrorText(woo, et, sizeof et);
- MessageBox(hwnd, et,
- rstring(IDS_T_ERR_OPEN_WAVE_INPUT), MB_OK | MB_ICONEXCLAMATION);
- GlobalFreePtr(wf);
- return FALSE;
- }
- break;
- }
- GlobalFreePtr(wf);
-
- /* Now allocate and prepare the sound input buffers. Don't
- you just love the code vomit Windows' inability to free
- resources when a program terminates creates? */
-
- currentInputLength = inputBufferLength();
- currentInputSamples = inputSampleCount();
- for (i = 0; i < nWaveHeaders; i++) {
- inWaveHeader[i] = NULL;
- }
- for (i = 0; i < nWaveHeaders; i++) {
- inWaveHeader[i] = (LPWAVEHDR) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE,
- sizeof(WAVEHDR));
- if (inWaveHeader[i] == NULL) {
- int j;
-
- for (j = i - 1; j >= 0; j++) {
- waveInUnprepareHeader(hWaveIn, inWaveHeader[j], sizeof(WAVEHDR));
- GlobalFreePtr(inWaveHeader[j]->lpData);
- GlobalFreePtr(inWaveHeader[j]);
- inWaveHeader[j] = NULL;
- }
- MessageBox(hwnd, rstring(IDS_T_INPUT_HEADER_ERR),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- waveInClose(hWaveIn);
- return FALSE;
- }
-
- /* Since the user is allowed to change the sample size
- and compression modes on the fly, but the audio input
- buffers are used for the entire run of the program, we
- allocate them for the worst-case scenario: both LPC and
- 2X compression enabled with 16 bit samples. We've already
- established whether the hardware can run at 8000 samples
- per second, so only allocate the larger buffer needed for
- 11025 sample per second hardware if it's actually required. */
-
- inWaveHeader[i]->lpData = (LPSTR) GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE,
- (DWORD) ((samplesPerSecond == 8000) ? 7200 : 10000));
- if (inWaveHeader[i]->lpData == NULL) {
- int j;
-
- GlobalFreePtr(inWaveHeader[i]);
- inWaveHeader[i] = 0;
- for (j = i - 1; j >= 0; j++) {
- waveInUnprepareHeader(hWaveIn, inWaveHeader[j], sizeof(WAVEHDR));
- GlobalFreePtr(inWaveHeader[j]->lpData);
- GlobalFreePtr(inWaveHeader[j]);
- inWaveHeader[j] = NULL;
- }
-
- MessageBox(hwnd, rstring(IDS_T_INPUT_BUFFER_ERR),
- NULL, MB_OK | MB_ICONEXCLAMATION);
- waveInClose(hWaveIn);
- return FALSE;
- }
-
- inWaveHeader[i]->dwBufferLength = currentInputLength;
- inWaveHeader[i]->dwFlags = 0;
- waveInPrepareHeader(hWaveIn, inWaveHeader[i], sizeof(WAVEHDR));
- }
-
- for (i = 0; i < nWaveHeaders; i++) {
- waveInAddBuffer(hWaveIn, inWaveHeader[i], sizeof(WAVEHDR));
- }
- inputTerm = FALSE;
- waveInStart(hWaveIn);
- inputActive = TRUE;
- aboutInSamples = samplesPerSecond;
- aboutInBits = bitsPerSample;
- propUpdateAudio();
- }
- return TRUE;
- }
-
- /* TERMINATEWAVEINPUT -- Shut down wave input and release all
- resources associated with it. */
-
- void terminateWaveInput(void)
- {
- if (inputActive) {
- int i;
-
- inputTerm = TRUE;
- waveInReset(hWaveIn);
- for (i = 0; i < nWaveHeaders; i++) {
- if (inWaveHeader[i] != NULL) {
- waveInUnprepareHeader(hWaveIn, inWaveHeader[i], sizeof(WAVEHDR));
- if (inWaveHeader[i]->lpData != NULL) {
- GlobalFreePtr(inWaveHeader[i]->lpData);
- }
- GlobalFreePtr(inWaveHeader[i]);
- inWaveHeader[i] = NULL;
- }
- }
- waveInClose(hWaveIn);
- hWaveIn = NULL;
- inputActive = FALSE;
- propUpdateAudio();
- }
- }
-
- /* REMEMBERNEWCONNECTION -- Add a connection file name to the list
- of remembered connections. If it's
- already in the list, promote it to the
- first item. */
-
- static void rememberNewConnection(LPSTR connectionFile)
- {
- int i;
- LPSTR hostSave;
-
- /* See if the connection file already appears in the list
- of recent connections. If so, delete it from the list. */
-
- hostSave = GlobalAllocPtr(GPTR, _fstrlen(connectionFile) + 1);
- _fstrcpy(hostSave, connectionFile);
-
- /* Careful! Be sure not to reference connectionFile beyond
- this point, since if we're re-opening a remembered
- connection the following loop may (in fact almost certainly
- will) cause it to be deallocated. */
-
- if (hostSave != NULL) {
- for (i = 0; i < rememberedConnections; i++) {
- if (_fstricmp(hostSave, rememberedConnection[i]) == 0) {
- int j;
-
- GlobalFreePtr(rememberedConnection[i]);
- for (j = i + 1; j < rememberedConnections; j++) {
- rememberedConnection[j - 1] = rememberedConnection[j];
- }
- rememberedConnections--;
- }
- }
-
- // Push the list of remembered connections and add this one
-
- if (rememberedConnections == REMEMBER_CONNECTIONS) {
- GlobalFreePtr(rememberedConnection[REMEMBER_CONNECTIONS - 1]);
- rememberedConnections--;
- }
- for (i = REMEMBER_CONNECTIONS - 1; i >= 1; i--) {
- rememberedConnection[i] = rememberedConnection[i - 1];
- }
- rememberedConnection[0] = hostSave;
- rememberedConnections++;
- }
- }
-
- /* NEWCONNECTION -- Initiate a connection to a given named
- host. If there's already a connection
- to this host active, activate its window. */
-
- VOID newConnection(HWND hwnd, LPSTR connectionFile, LPSTR knownHost)
- {
- CHAR szHostName[MAX_HOST];
- SOCKADDR_IN sockHost;
- #define addrHost sockHost.sin_addr
- LPCLIENT_DATA pClientData = NULL;
- HWND hwndClient;
- char *cg;
-
- // Prompt the user for a new host
-
- if (connectionFile == NULL) {
- if (knownHost == NULL) {
- if (!newHostDialogue(hwndMDIFrame, szHostName, &addrHost)) {
- return;
- }
- } else {
- wsprintf(szHostName, Format(61), knownHost);
- addrHost.s_addr = inet_addr(knownHost);
- }
- } else {
- char inetAddr[64];
-
- cg = rstring(IDS_PF_HOST);
- if (GetPrivateProfileString(cg, rstring(IDS_PF_HOST_NAME), "", szHostName,
- sizeof szHostName, connectionFile) == 0 ||
- GetPrivateProfileString(cg, rstring(IDS_PF_NETADDR), "", inetAddr,
- sizeof inetAddr, connectionFile) == 0 ||
- (addrHost.s_addr = inet_addr(inetAddr)) == INADDR_NONE) {
- MessageBox(hwnd, rstring(IDS_T_CONN_PROFILE_INVALID), connectionFile,
- MB_OK | MB_ICONEXCLAMATION);
- return;
- }
- }
-
- /* See if there's already a client window communicating with
- this host. Use equality of IP number as the criterion to
- prevent spoofing due to aliases. */
-
- hwndClient = findClientByHost(&sockHost);
-
- if (hwndClient != NULL) {
- if (IsIconic(hwndClient)) {
- FORWARD_WM_MDIRESTORE(hwndMDIClient, hwndClient, SendMessage);
- }
- BringWindowToTop(hwndClient);
- pClientData = CLIENTPTR(hwndClient);
- } else {
-
- // Allocate a new connection structure
-
- pClientData = (LPCLIENT_DATA) GlobalAllocPtr(GPTR, sizeof(CLIENT_DATA));
-
- if (pClientData != NULL) {
-
- // Initialize the connection descriptor
-
- _fmemset(pClientData, 0, sizeof(CLIENT_DATA));
- pClientData->dwType = WINDOW_TYPE_CLIENT;
- pClientData->wantsInput = FALSE;
- pClientData->broadcastBeginTime = GetTickCount();
- pClientData->broadcastEnd = FALSE;
- pClientData->state = Embryonic;
- pClientData->sReply = INVALID_SOCKET;
- pClientData->timeout = -1; // Connection with local origin is immortal
- pClientData->inetSock.sin_addr.s_addr = addrHost.s_addr;
- pClientData->modemConnection = (addrHost.s_addr == 0);
- pClientData->hFile = HFILE_ERROR;
- pClientData->multicast_scope = 1;
- pClientData->szFile[0] = '\0';
-
- _fstrcpy(pClientData->szHost, szHostName);
- } else {
- return;
- }
-
- // Create the connection child window
-
- hwndClient = createNewConnection(pClientData);
-
- if (hwndClient == NULL) {
- GlobalFreePtr(pClientData);
- return;
- }
- }
-
- /* If the connection was defined in a file, restore the
- parameters to those saved in the file. */
-
- if (connectionFile != NULL) {
-
- _fstrcpy(pClientData->connectionFileName, connectionFile);
-
- cg = rstring(IDS_PF_DEBUG);
- pClientData->debugging = GetPrivateProfileInt(cg,
- rstring(IDS_PF_DEBUGGING), FALSE, connectionFile);
- pClientData->loopback = GetPrivateProfileInt(cg,
- rstring(IDS_PF_LOOPBACK), FALSE, connectionFile);
-
- cg = rstring(IDS_PF_MULTICAST);
- pClientData->multicast_scope = GetPrivateProfileInt(cg,
- rstring(IDS_PF_SCOPE), 1, connectionFile);
-
- cg = rstring(IDS_PF_ENCRYPTION);
- pClientData->saveKeys = GetPrivateProfileInt(cg,
- rstring(IDS_PF_SAVE_KEYS), FALSE, connectionFile);
- GetPrivateProfileString(cg, rstring(IDS_PF_PGP_USER_NAMES), "",
- pClientData->opgpUserList,
- sizeof pClientData->opgpUserList, connectionFile);
- if (pClientData->saveKeys) {
- GetPrivateProfileString(cg, rstring(IDS_PF_DES_KEY), "",
- pClientData->desKeyString,
- sizeof pClientData->desKeyString, connectionFile);
- GetPrivateProfileString(cg, rstring(IDS_PF_IDEA_KEY), "",
- pClientData->ideaKeyString,
- sizeof pClientData->ideaKeyString, connectionFile);
- GetPrivateProfileString(cg, rstring(IDS_PF_KEY_FILE), "",
- pClientData->otpFileName,
- sizeof pClientData->otpFileName, connectionFile);
- }
-
- // Initialise settings derived from saved parameters
-
- if (!makeInternalEncryptionKeys(hwndClient, pClientData)) {
- pClientData->otpFileName[0] = 0;
- }
-
- /* Caution: don't reference connectionFile anywhere after
- the call to rememberNewConnection. If we're re-opening
- a remembered connection, the call may release it. */
-
- rememberNewConnection(connectionFile);
- }
- #undef addrHost
- }
-
- /* PGPSETSESSIONKEY -- If needed, invoke PGP to decrypt the session
- key and set it in effect for PGP encrypted
- packets. */
-
- static void pgpSetSessionKey(HWND hwnd, LPCLIENT_DATA conn, soundbuf *d)
- {
- char cmd[MAX_PATH + 40], kmd[16];
- HFILE kfile;
- struct MD5Context md5c;
-
- MD5Init(&md5c);
- MD5Update(&md5c, d->buffer.buffer_val, (unsigned) d->buffer.buffer_len);
- MD5Final(kmd, &md5c);
-
- if (_fmemcmp(conn->pgpkeymd5, kmd, 16) != 0) {
- conn->pgpkey[0] = FALSE;
- _fmemcpy(conn->pgpkeymd5, kmd, 16);
- GetTempFileName(0, "PK", 0, conn->pgpFileName);
-
- kfile = _lcreat(conn->pgpFileName, 0);
- if (kfile == NULL) {
- MessageBox(hwnd, rstring(IDS_T_OPEN_SESSION_KEY_FILE_ERR),
- rstring(IDS_T_PGP_KEY_ERR_TITLE), MB_ICONEXCLAMATION | MB_OK);
- } else {
- UINT execStat = 0;
-
- _lwrite(kfile, d->buffer.buffer_val, (UINT) d->buffer.buffer_len);
- _lclose(kfile);
-
- /* First try to run PGP via the PIF in our own directory. This
- guarantees it's run with the modes we've chosen, such as
- in a window rather than full-screen. */
-
- if (GetModuleFileName(hInst, cmd, sizeof cmd) > 0) {
- char *cp = cmd + strlen(cmd);
-
- while (cp >= cmd && *cp != '\\' && *cp != ':') {
- cp--;
- }
- cp[1] = 0;
- wsprintf(cmd + strlen(cmd), Format(52), conn->pgpFileName);
- execStat = WinExec(cmd, SW_SHOW);
- }
-
- /* If that didn't work, attempt to run PGP by straight path
- search using the default modes. */
-
- if (execStat < 32) {
- wsprintf(cmd, Format(1), conn->pgpFileName);
- execStat = WinExec(cmd, SW_SHOW);
- }
-
- // Set timer to poll for completion of decoding
-
- if (execStat >= 32) {
- conn->pgpFileName[_fstrlen(conn->pgpFileName) - 4] = 0;
- SetTimer(hwnd, 3, 1000, NULL);
- } else {
- wsprintf(cmd + strlen(cmd), Format(51), execStat);
- MessageBox(hwnd, cmd, rstring(IDS_T_CANT_INVOKE_PGP),
- MB_OK | MB_ICONEXCLAMATION);
- }
- }
- }
- }
-
- // onCreate -- Initialise frame window when newly created
-
- static BOOL onCreate(HWND hwnd, CREATESTRUCT FAR *pCreateStruct)
- {
- CLIENTCREATESTRUCT ccs;
- WSADATA wsadata;
- SOCKERR serr;
- HDC hdc;
- TEXTMETRIC tm;
- int i, j;
- char *cg;
- char pfn[80];
- char md5key[16];
-
- // Initialize the sockets library
-
- serr = WSAStartup(DESIRED_WINSOCK_VERSION, &wsadata);
-
- if (serr != 0) {
- MsgBox(NULL, MB_ICONSTOP | MB_OK, Format(12), serr, SockerrToString(serr));
- return FALSE;
- }
-
- if (wsadata.wVersion < MINIMUM_WINSOCK_VERSION) {
- MsgBox(NULL, MB_ICONSTOP | MB_OK, Format(13), LOBYTE(wsadata.wVersion),
- HIBYTE(wsadata.wVersion), LOBYTE(MINIMUM_WINSOCK_VERSION),
- HIBYTE(MINIMUM_WINSOCK_VERSION));
- return FALSE;
- }
- aboutUDPmax = wsadata.iMaxUdpDg;
-
- /* If the network can't transmit sound packets as large as we'd like
- to send, restrict the size to what it can accommodate. */
-
- if (aboutUDPmax > 0) {
- if ((netMaxSamples + (sizeof(soundbuf) - BUFL) + 40) > (WORD) aboutUDPmax) {
- netMaxSamples = aboutUDPmax - ((sizeof(soundbuf) - BUFL) + 40);
- }
- }
-
- // Create the command socket
-
- serr = CreateSocket(&sCommand, SOCK_DGRAM, htonl(INADDR_ANY), htons(NETFONE_COMMAND_PORT));
- if (serr != 0) {
- MsgBox(NULL, MB_ICONSTOP | MB_OK, Format(14),
- serr, SockerrToString(serr));
- return FALSE;
- }
-
- // Load cursors
-
- phoneCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR_PHONE));
- earCursor = LoadCursor(hInst, MAKEINTRESOURCE(IDC_CURSOR_EAR));
-
- // Register the message for file open/save help button pressed
-
- fileOpenHelpButton = RegisterWindowMessage(HELPMSGSTRING);
-
- // Initialise GSM encoding and decoding
-
- gsmh = gsm_create();
-
- // Initialise LPC encoding and decoding
-
- lpc_init(180);
-
- // Initialise DES
-
- desinit(1);
-
- // Initialise RTP randomised parameters
-
- sessionKeyGenerate(md5key, TRUE);
- _fmemcpy((char *) &ssrc, md5key, sizeof ssrc);
- _fmemcpy((char *) ×tamp, md5key + sizeof ssrc,
- sizeof timestamp);
- _fmemcpy((char *) &seq, md5key + sizeof ssrc + sizeof timestamp,
- sizeof seq);
-
- // Create the MDI client window
-
- ccs.hWindowMenu = GetSubMenu(GetMenu(hwnd), 3); // Identify Window menu
- ccs.idFirstChild = IDM_WINDOW_FIRST_CHILD;
-
- hwndMDIClient = CreateWindow(pszMDIClientClass, NULL,
- WS_CHILD | WS_CLIPCHILDREN | WS_VSCROLL | WS_HSCROLL,
- 0, 0, 0, 0, hwnd, 0, hInst, (LPSTR) &ccs);
-
- if (hwndMDIClient == NULL) {
- return FALSE;
- }
-
- ShowWindow(hwndMDIClient, SW_SHOW);
-
- _fstrcpy(pfn, rstring(IDS_PF_PROFILE_FILE));
-
- // Load remembered recent connections
-
- cg = rstring(IDS_PF_CONNECTIONS);
- rememberedConnections = GetPrivateProfileInt(cg, rstring(IDS_PF_CONNCOUNT),
- 0, pfn);
- if (rememberedConnections > REMEMBER_CONNECTIONS) {
- rememberedConnections = REMEMBER_CONNECTIONS;
- }
- for (i = j = 0; i < rememberedConnections; i++) {
- char psn[12], rcr[MAX_HOST];
-
- wsprintf(psn, Format(2), i + 1);
- GetPrivateProfileString(cg, psn, "", rcr,
- sizeof rcr, pfn);
- if (_fstrlen(rcr) > 0) {
- LPSTR rcon = (LPSTR) GlobalAllocPtr(GPTR, _fstrlen(rcr) + 1);
-
- if (rcon!= NULL) {
- _fstrcpy(rcon, rcr);
- rememberedConnection[j++] = rcon;
- }
- }
- }
- rememberedConnections = j;
-
- // Restore multicast group memberships
-
- cg = rstring(IDS_PF_MULTIGROUPS);
- multiMemberships = GetPrivateProfileInt(cg, rstring(IDS_PF_CONNCOUNT),
- 0, pfn);
- if (multiMemberships > IP_MAX_MEMBERSHIPS) {
- multiMemberships = IP_MAX_MEMBERSHIPS;
- }
- for (i = 0; i < multiMemberships; i++) {
- char psn[24], rcr[MAX_HOST];
-
- wsprintf(psn, Format(3), i + 1);
- GetPrivateProfileString(cg, psn, "", rcr,
- sizeof rcr, pfn);
- multiAddr[i].s_addr = inet_addr(rcr);
- wsprintf(psn, Format(4), i + 1);
- GetPrivateProfileString(cg, psn, "", rcr, sizeof rcr, pfn);
- multiName[i] = NULL;
- if (_fstrlen(rcr) > 0) {
- LPSTR rcon = (LPSTR) GlobalAllocPtr(GPTR, _fstrlen(rcr) + 1);
-
- if (rcon!= NULL) {
- _fstrcpy(rcon, rcr);
- multiName[i] = rcon;
- }
- }
- }
- multiLoop = GetPrivateProfileInt(cg, rstring(IDS_PF_LOOPBACK), TRUE, pfn);
- multicastJoin(hwnd, TRUE);
-
- // Restore compression modes
-
- #define BoolProfile(var, section, itemname, defval) var = GetPrivateProfileInt(section, itemname, defval, pfn)
- cg = rstring(IDS_PF_COMPRESSION);
- BoolProfile(compression, cg, rstring(IDS_PF_COMP_SIMPLE), FALSE);
- BoolProfile(gsmcompress, cg, rstring(IDS_PF_COMP_GSM), TRUE);
- BoolProfile(adpcmcompress, cg, rstring(IDS_PF_COMP_ADPCM), FALSE);
- BoolProfile(lpccompress, cg, rstring(IDS_PF_COMP_LPC), FALSE);
-
- // Restore modem configuration and initialise if enabled
-
- cg = rstring(IDS_PF_MODEM);
- BoolProfile(modemEnable, cg, rstring(IDS_PF_ENABLE), FALSE);
- GetPrivateProfileString(cg, rstring(IDS_PF_PORT), "COM1", commport,
- sizeof commport, pfn);
- GetPrivateProfileString(cg, rstring(IDS_PF_BAUDRATE), "19200", baudrate,
- sizeof baudrate, pfn);
- GetPrivateProfileString(cg, rstring(IDS_PF_MODEM_INIT_STRING), "ATQ0V1E1S0=1",
- modemInitString, sizeof modemInitString, pfn);
- BoolProfile(modemShowRant, cg, rstring(IDS_PF_SHOW_RANT), TRUE);
-
- // Restore answering machine settings
-
- cg = rstring(IDS_PF_ANSWER);
- GetPrivateProfileString(cg, rstring(IDS_PF_FILE_NAME), "", answerFileName,
- sizeof answerFileName, pfn);
- BoolProfile(answerRecord, cg, rstring(IDS_PF_RECORD_MESSAGES), FALSE);
-
- // Restore in your face settings
-
- GetPrivateProfileString(rstring(IDS_PF_FACE), rstring(IDS_PF_FILE_NAME), "", faceFileName,
- sizeof faceFileName, pfn);
- BoolProfile(faceShow, rstring(IDS_PF_FACE), rstring(IDS_PF_SHOW_FACES), TRUE);
-
- // Restore miscellaneous configuration parameters
-
- GetPrivateProfileString(rstring(IDS_PF_RING), rstring(IDS_PF_FILE_NAME), "",
- ringFileName, sizeof ringFileName, pfn);
- BoolProfile(lookWho_sTalking, rstring(IDS_PF_PREFERENCES), rstring(IDS_PF_LOOKWHO), FALSE);
-
- // Restore Look Who's Listening parameters
-
- GetPrivateProfileString(rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_SERVER), "",
- lwl_s_server, sizeof lwl_s_server, pfn);
- GetPrivateProfileString(rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_EMAIL), "",
- lwl_s_email, sizeof lwl_s_email, pfn);
- GetPrivateProfileString(rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_FULLNAME), "",
- lwl_s_fullname, sizeof lwl_s_fullname, pfn);
- GetPrivateProfileString(rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_PHONE), "",
- lwl_s_phone, sizeof lwl_s_phone, pfn);
- GetPrivateProfileString(rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_LOCATION), "",
- lwl_s_location, sizeof lwl_s_location, pfn);
- BoolProfile(lwl_s_publish, rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_PUBLISH), FALSE);
- BoolProfile(lwl_s_exact, rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_EXACT), FALSE);
-
- GetPrivateProfileString(rstring(IDS_PF_LWL_ASK), rstring(IDS_PF_SERVER), "",
- lwl_a_server, sizeof lwl_a_server, pfn);
- BoolProfile(lwl_a_exact, rstring(IDS_PF_LWL_ASK), rstring(IDS_PF_EXACT), FALSE);
-
- // Restore bug workaround parameters
-
- cg = rstring(IDS_PF_WORKAROUNDS);
- BoolProfile(alwaysBindSocket, cg, rstring(IDS_PF_ALWAYS_BIND), FALSE);
- BoolProfile(waNetNoConnect, cg, rstring(IDS_PF_NET_NO_CONNECT), FALSE);
- BoolProfile(waNetUseSend, cg, rstring(IDS_PF_NET_USE_SEND), FALSE);
- BoolProfile(waNetMultiTTLisChar, cg, rstring(IDS_PF_MULTICAST_CHAR_ARG), FALSE);
- BoolProfile(waAudioHalf, cg, rstring(IDS_PF_AUDIO_HALF_DUPLEX), FALSE);
- BoolProfile(waAudio11025, cg, rstring(IDS_PF_AUDIO_SAMPLE_11025), FALSE);
- #undef BoolProfile
- useSendNotSendto = waNetUseSend;
-
- // Check out the audio hardware
-
- halfDuplex = isHalfDuplex(hwnd);
-
- // Create the timeout timer
-
- if (SetTimer(hwnd, FRAME_TIMER_ID, 1000, NULL) == 0) {
- MsgBox(NULL, MB_ICONSTOP | MB_OK, Format(15));
- return FALSE;
- }
-
- // Calculate packet size based on selected modes
-
- currentInputLength = inputBufferLength();
- currentInputSamples = inputSampleCount();
-
- // Get textmetric data
-
- hdc = GetDC(hwnd);
- GetTextMetrics(hdc, &tm);
- ReleaseDC(hwnd, hdc);
-
- tmAveCharWidth = (INT)tm.tmAveCharWidth;
- tmHeight = (INT)tm.tmHeight;
- pfnPropeller = MakeProcInstance((FARPROC) propellerHeadDlgProc, hInst);
- pfnAnswer = MakeProcInstance((FARPROC) answerDlgProc, hInst);
-
- /* If we were invoked with file names on the command line,
- as happens when a .SFX file is double clicked in the File
- Manager (assuming the association has been made), open the
- specified connection files. */
-
- if (commandLine != NULL) {
- LPSTR cln, clp = commandLine;
-
- while (_fstrlen(clp) > 0) {
- while (_fstrlen(clp) > 0 && isspace(*clp)) {
- clp++;
- }
- if (*clp == 0) {
- break;
- }
- cln = _fstrchr(clp, ' ');
- if (cln != NULL) {
- *cln = 0;
- }
- newConnection(hwnd, clp, NULL);
- if (cln == NULL) {
- break;
- }
- clp = cln + 1;
- }
- GlobalFreePtr(commandLine);
- commandLine = NULL;
- }
-
- DragAcceptFiles(hwnd, TRUE);
-
- /* If an answering machine message file was named, open
- it. This doesn't imply we're recording messages; that's
- controlled by answerRecord. */
-
- if (answerFileName[0] != 0) {
- answerOpen();
- }
-
- // Open the face image file, if any
-
- V openFaceFile(hwnd);
-
- /* If we're publishing our information with a Look Who's Listening
- server, establish contact with it. */
-
- V lwl_reconnect(hwnd);
-
- // Finally, open the input socket for business.
-
-
- if (WSAAsyncSelect(sCommand, hwnd, WM_SOCKET_SELECT, FD_READ) != 0) {
- serr = WSAGetLastError();
- }
- if (serr != 0) {
- MsgBox(NULL, MB_ICONSTOP | MB_OK, Format(14),
- serr, SockerrToString(serr));
- }
- return TRUE;
- }
-
- /* onCommand -- Dispatch WM_COMMAND messages. Some are processed
- at the frame level, some sent to the MDI client,
- and others forwarded to the active MDI connection
- window. */
-
- static VOID onCommand(HWND hwnd, INT id, HWND hwndCtl, UINT codeNotify)
- {
- if (id > IDM_CUSTOM && id <= (IDM_CUSTOM + rememberedConnections)) {
- newConnection(hwnd, rememberedConnection[(id - IDM_CUSTOM) - 1], NULL);
- return;
- }
-
- switch (id) {
-
- case IDM_CONNECTION_NEW:
- newConnection(hwnd, NULL, NULL);
- break;
-
- case IDM_CONN_OPEN:
- {
- OPENFILENAME ofn;
- char cfName[MAX_PATH];
-
- memset(&ofn, 0, sizeof(ofn));
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = hwnd;
- ofn.lpstrFilter = rfilter(IDS_T_CONNECTION_FILTER);
- ofn.lpstrCustomFilter = NULL;
- cfName[0] = 0;
- ofn.lpstrFile = (LPSTR) cfName;
- ofn.nMaxFile = sizeof cfName;
- ofn.lpstrInitialDir = NULL;
- ofn.lpstrTitle = rstring(IDS_T_CONNECTION_OPEN_TITLE);
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_SHOWHELP;
- fileHelpKey = rstring(IDS_HELP_OPEN_CONNECTION);
- if (GetOpenFileName((LPOPENFILENAME) &ofn) == 0) {
- break;
- }
- newConnection(hwnd, cfName, NULL);
- }
- break;
-
- case IDM_CONN_SAVE_AS:
- {
- OPENFILENAME ofn;
- HWND cWnd = getActiveConnection();
-
- if (cWnd != NULL) {
- LPCLIENT_DATA d = CLIENTPTR(cWnd);
-
- d->timeout = -1; // Make connection immortal
- memset(&ofn, 0, sizeof(ofn));
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = hwnd;
- ofn.lpstrDefExt = "SFX";
- ofn.lpstrFilter = rfilter(IDS_T_CONNECTION_FILTER);
- ofn.lpstrCustomFilter = NULL;
- d->szFile[0] = 0;
- ofn.lpstrFile = (LPSTR) d->connectionFileName;
- ofn.nMaxFile = sizeof d->connectionFileName;
- ofn.lpstrInitialDir = NULL;
- ofn.lpstrTitle = rstring(IDS_T_CONNECTION_SAVE_TITLE);
- ofn.Flags = OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT |
- OFN_HIDEREADONLY | OFN_SHOWHELP;
- fileHelpKey = rstring(IDS_HELP_SAVE_CONNECTION);
- if (GetSaveFileName((LPOPENFILENAME) &ofn) == 0) {
- break;
- }
- }
- }
- // Wheee!!! Note fall-through
-
- case IDM_CONN_SAVE:
- {
- HWND cWnd = getActiveConnection();
-
- if (cWnd != NULL) {
- LPCLIENT_DATA d = CLIENTPTR(cWnd);
- char mcs[10];
-
- wsprintf(mcs, Format(5), d->multicast_scope);
- d->timeout = -1; // Make connection immortal
- if (WritePrivateProfileString(rstring(IDS_PF_HOST), rstring(IDS_PF_HOST_NAME),
- d->szHost, d->connectionFileName) == 0 ||
- WritePrivateProfileString(rstring(IDS_PF_HOST), rstring(IDS_PF_NETADDR),
- inet_ntoa(d->inetSock.sin_addr), d->connectionFileName) == 0 ||
- WritePrivateProfileString(rstring(IDS_PF_DEBUG), rstring(IDS_PF_DEBUGGING),
- d->debugging ? kS1 : kS0, d->connectionFileName) == 0 ||
- WritePrivateProfileString(rstring(IDS_PF_DEBUG), rstring(IDS_PF_LOOPBACK),
- d->loopback ? kS1 : kS0, d->connectionFileName) == 0 ||
- WritePrivateProfileString(rstring(IDS_PF_MULTICAST), rstring(IDS_PF_SCOPE),
- mcs, d->connectionFileName) == 0 ||
- WritePrivateProfileString(rstring(IDS_PF_ENCRYPTION), rstring(IDS_PF_SAVE_KEYS),
- d->saveKeys ? kS1 : kS0, d->connectionFileName) == 0 ||
- WritePrivateProfileString(rstring(IDS_PF_ENCRYPTION), rstring(IDS_PF_PGP_USER_NAMES),
- d->opgpUserList, d->connectionFileName) == 0 |
- (!d->saveKeys ? 0 : (
- WritePrivateProfileString(rstring(IDS_PF_ENCRYPTION), rstring(IDS_PF_DES_KEY),
- d->desKeyString, d->connectionFileName) == 0 ||
- WritePrivateProfileString(rstring(IDS_PF_ENCRYPTION), rstring(IDS_PF_IDEA_KEY),
- d->ideaKeyString, d->connectionFileName) == 0 ||
- WritePrivateProfileString(rstring(IDS_PF_ENCRYPTION), rstring(IDS_PF_KEY_FILE),
- d->otpFileName, d->connectionFileName) == 0))) {
- MessageBox(hwnd, rstring(IDS_T_CONN_SAVE_ERR), NULL,
- MB_OK | MB_ICONEXCLAMATION);
- } else {
- rememberNewConnection(d->connectionFileName);
- }
- }
- }
- break;
-
- case IDM_CONN_PROPERTIES:
- {
- HWND cWnd = getActiveConnection();
-
- if (cWnd != NULL) {
- CLIENTPTR(cWnd)->timeout = -1; // Make connection immortal
- connectionProperties(cWnd, CLIENTPTR(cWnd));
- }
- }
- break;
-
- case IDM_CONN_RING:
- {
- HWND cWnd = getActiveConnection();
-
- if (cWnd != NULL) {
- CLIENTPTR(cWnd)->ring = TRUE;
- }
- }
- // Wheee!!! Fall through into Send Sound File
-
- case IDM_SEND_SOUND_FILE:
- {
- OPENFILENAME ofn;
- HWND cWnd = getActiveConnection();
-
- if (cWnd != NULL) {
- LPCLIENT_DATA d = CLIENTPTR(cWnd);
- int originalTimeout = d->timeout;
-
- /* Make the window "temporarily immortal" so it doesn't
- disappear due to timeout while the send file dialogue
- is up. */
- d->timeout = -1;
- if (d->hFile == HFILE_ERROR && d->mmioHandle == NULL) {
- int s = FALSE;
-
- memset(&ofn, 0, sizeof(ofn));
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = hwnd;
- ofn.lpstrFilter = rfilter(IDS_T_SOUND_FILE_FILTER);
- ofn.lpstrCustomFilter = NULL;
- d->szFile[0] = 0;
- ofn.lpstrFile = (LPSTR) d->szFile;
- ofn.nMaxFile = sizeof(d->szFile);
- ofn.lpstrInitialDir = NULL;
- ofn.lpstrTitle = d->ring ? rstring(IDS_T_RING_TITLE) :
- rstring(IDS_T_SEND_SOUND_TITLE);
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_SHOWHELP;
- fileHelpKey = d->ring ? rstring(IDS_HELP_RING_FILE) :
- rstring(IDS_HELP_SEND_SOUND_FILE);
- if (d->ring && ringFileName[0] != 0) {
- HFILE hFile;
-
- hFile = _lopen(ringFileName, OF_READ | OF_SHARE_DENY_WRITE);
- if (hFile != HFILE_ERROR) {
- _lclose(hFile);
- _fstrcpy(d->szFile, ringFileName);
- s = TRUE;
- }
- }
- if (!s) {
- s = GetOpenFileName((LPOPENFILENAME) &ofn);
- if (d->ring) {
- _fstrcpy(ringFileName, d->szFile);
- }
- }
- if (s) {
- startSoundFile(cWnd, d->szFile);
- } else {
- /* User canceled send file dialogue. Restore
- timeout to the original value. */
- d->timeout = originalTimeout;
- }
- } else {
- d->quitSoundFile = TRUE;
- }
- }
- }
- break;
-
- case IDM_CO_REPONDEUR:
- answerDialogue(hwnd);
- break;
-
- case IDM_CO_RECORD:
- answerRecord = !answerRecord;
- if (hDlgAnswer != NULL) {
- CheckDlgButton(hDlgAnswer, IDC_RP_RECORD, answerEnabled() && answerRecord);
- }
- break;
-
- case IDM_CONN_BROADCAST:
- broadcasting = !broadcasting;
- if (broadcasting) {
- HWND hwnd = GetWindow(hwndMDIClient, GW_CHILD);
- DWORD bstart = GetTickCount();
-
- // Clear wants input in any sending windows
-
- while (hwnd != NULL) {
- if ((WNDPROC) GetWindowLong(hwnd, GWL_WNDPROC) == ((WNDPROC) connectWndProc)) {
- LPCLIENT_DATA pClientData = CLIENTPTR(hwnd);
-
- if (pClientData != NULL) {
- pClientData->wantsInput = FALSE;
- pClientData->broadcastBeginTime = bstart;
- pClientData->broadcastEnd = FALSE;
- }
- }
- hwnd = GetWindow(hwnd, GW_HWNDNEXT);
- }
- listeners = 0;
- if (!inputActive) {
- V startWaveInput(hwnd);
- }
- } else {
- terminateWaveInput();
- SetCursor(LoadCursor(NULL, IDC_ARROW));
- }
- SetWindowText(hwndMDIFrame, rstring(broadcasting ?
- IDS_T_APP_TITLE_BROADCAST : IDS_T_APP_TITLE_NORM));
- break;
-
- case IDM_RING_FILE_NAME:
- {
- OPENFILENAME ofn;
- char fName[MAX_PATH];
-
- memset(&ofn, 0, sizeof(ofn));
- ofn.lStructSize = sizeof(OPENFILENAME);
- ofn.hwndOwner = hwnd;
- ofn.lpstrFilter = rfilter(IDS_T_SOUND_FILE_FILTER);
- ofn.lpstrCustomFilter = NULL;
- _fstrcpy(fName, ringFileName);
- ofn.lpstrFile = (LPSTR) fName;
- ofn.nMaxFile = sizeof(fName);
- ofn.lpstrInitialDir = NULL;
- ofn.lpstrTitle = rstring(IDS_T_RING_TITLE);
- ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_SHOWHELP;
- fileHelpKey = rstring(IDS_HELP_RING_FILE);
- if (GetOpenFileName((LPOPENFILENAME) &ofn)) {
- _fstrcpy(ringFileName, fName);
- }
- }
- break;
-
- case IDM_CONN_MULTICAST:
- multicastGroupsDialogue(hwnd);
- break;
-
- case IDM_DISCONNECT:
- {
- LRESULT mdiActive = SendMessage(hwndMDIClient, WM_MDIGETACTIVE,
- 0, 0L);
- if (LOWORD(mdiActive) != NULL) {
- PostMessage((HWND) LOWORD(mdiActive), WM_CLOSE, 0, 0L);
- }
- }
- break;
-
- case IDM_OPT_8BIT:
- audioUse8Bit = !audioUse8Bit;
- if (!audioUse8Bit && !audioIs8Bit) {
- sampleAlignment = 2;
- bitsPerSample = 16;
- } else {
- sampleAlignment = 1;
- bitsPerSample = 8;
- }
- bytesPerSecond = samplesPerSecond * sampleAlignment;
- propUpdateAudio();
- break;
-
- case IDM_OPT_LOOK_WHO:
- lookWho_sTalking = !lookWho_sTalking;
- break;
-
- case IDM_WORKA_BIND:
- alwaysBindSocket = !alwaysBindSocket;
- break;
-
- case IDM_WORKA_NOCONNECT:
- waNetNoConnect = !waNetNoConnect;
- if (waNetNoConnect) {
- waNetUseSend = FALSE;
- }
- break;
-
- case IDM_WORKA_USE_SEND:
- waNetUseSend = !waNetUseSend;
- useSendNotSendto = waNetUseSend;
- if (waNetUseSend) {
- waNetNoConnect = FALSE;
- }
- if (hDlgPropeller != NULL) {
- SetDlgItemText(hDlgPropeller, IDC_PH_SENDTO,
- useSendNotSendto ? rstring(IDS_T_SEND) : rstring(IDS_T_SENDTO));
- }
- break;
-
- case IDM_WORKA_TTLCHAR:
- waNetMultiTTLisChar = !waNetMultiTTLisChar;
- break;
-
- case IDM_WORKA_HALF_DUPLEX:
- waAudioHalf = !waAudioHalf;
- MessageBox(hwnd, rstring(IDS_T_EXIT_AND_RESTART), pszAppName,
- MB_OK | MB_ICONINFORMATION);
- break;
-
- case IDM_WORKA_SAMPLE_11025:
- waAudio11025 = !waAudio11025;
- MessageBox(hwnd, rstring(IDS_T_EXIT_AND_RESTART), pszAppName,
- MB_OK | MB_ICONINFORMATION);
- break;
-
- case IDM_COMP_2X:
- compression = !compression;
- currentInputLength = inputBufferLength();
- currentInputSamples = inputSampleCount();
- propUpdateAudio();
- break;
-
- case IDM_COMP_ADPCM:
- adpcmcompress = !adpcmcompress;
- if (adpcmcompress) {
- gsmcompress = FALSE;
- lpccompress = FALSE;
- }
- currentInputLength = inputBufferLength();
- currentInputSamples = inputSampleCount();
- propUpdateAudio();
- break;
-
- case IDM_COMP_LPC:
- lpccompress = !lpccompress;
- if (lpccompress) {
- gsmcompress = FALSE;
- adpcmcompress = FALSE;
- }
- currentInputLength = inputBufferLength();
- currentInputSamples = inputSampleCount();
- propUpdateAudio();
- break;
-
- case IDM_COMP_GSM:
- gsmcompress = !gsmcompress;
- if (gsmcompress) {
- adpcmcompress = FALSE;
- lpccompress = FALSE;
- }
- currentInputLength = inputBufferLength();
- currentInputSamples = inputSampleCount();
- propUpdateAudio();
- break;
-
- case IDM_OPT_MODEM:
- modemSetupDialogue(hwnd);
- break;
-
- case IDM_OPT_FACE:
- faceDialogue(hwnd);
- break;
-
- case IDM_CRYPTO_GENKEY:
- genKeyDialogue(hwnd);
- break;
-
- case IDM_CONNECTION_EXIT:
- PostMessage(hwnd, WM_CLOSE, 0, 0);
- break;
-
- case IDM_DIR_SEARCH:
- lwl_t_diactive = TRUE;
- lwl_ask(hwnd);
- lwl_t_diactive = FALSE;
- break;
-
- case IDM_DIR_LISTING:
- lwl_t_diactive = TRUE;
- lwl_tell_settings(hwnd);
- lwl_t_diactive = FALSE;
- break;
-
- case IDM_WINDOW_CASCADE:
- FORWARD_WM_MDICASCADE(hwndMDIClient, 0, SendMessage);
- break;
-
- case IDM_WINDOW_TILE_VERTICALLY:
- FORWARD_WM_MDITILE(hwndMDIClient, MDITILE_VERTICAL, SendMessage);
- break;
-
- case IDM_WINDOW_TILE_HORIZONTALLY :
- FORWARD_WM_MDITILE(hwndMDIClient, MDITILE_HORIZONTAL, SendMessage);
- break;
-
- case IDM_WINDOW_ARRANGE_ICONS:
- FORWARD_WM_MDIICONARRANGE(hwndMDIClient, SendMessage);
- break;
-
- case IDM_HELP_CONT:
- WinHelp(hwnd, rstring(IDS_HELPFILE), HELP_CONTENTS, 0L);
- holped = TRUE;
- break;
-
- case IDM_HELP_SEARCH:
- WinHelp(hwnd, rstring(IDS_HELPFILE), HELP_PARTIALKEY, ((DWORD) ((LPSTR) "")));
- holped = TRUE;
- break;
-
- case IDM_PROPELLER_HEAD:
- propellerHeadDialogue(hwnd);
- break;
-
- case IDM_HELP_ABOUT:
- aboutDialogue(hwnd);
- break;
-
- case IDM_MODEM_RANT:
- modemRant(hwnd);
- break;
-
- default:
- FORWARD_WM_COMMAND(hwnd, id, hwndCtl,
- codeNotify, Frame_MDIMessageForwarder);
- break;
- }
- }
-
- // OBTAINOUTPUT -- Try to obtain control of wave audio output
-
- int obtainOutput(HWND hwnd)
- {
-
- // Grab the audio device if we don't already have it
-
- outputTimeout = 0; // Reset release output timeout
- if (!outputActive) {
- LPPCMWAVEFORMAT wf;
- WORD woo;
-
- /* If we already know the port is half duplex, just ditch the
- packet right away rather than walking into the door again. */
-
- if (halfDuplex && inputActive) {
- propeller(IDC_PH_INPUT_LOST, ++inputPacketsLost);
- return FALSE;
- } else {
-
- wf = (LPPCMWAVEFORMAT) GlobalAllocPtr(GPTR, sizeof(PCMWAVEFORMAT));
- if (wf == NULL) {
- return FALSE;
- }
- wf->wf.wFormatTag = WAVE_FORMAT_PCM;
- wf->wf.nChannels = audioChannels;
- wf->wf.nSamplesPerSec = samplesPerSecond;
- wf->wf.nAvgBytesPerSec = bytesPerSecond;
- wf->wf.nBlockAlign = sampleAlignment;
- wf->wBitsPerSample = bitsPerSample;
- while (TRUE) {
- woo = waveOutOpen(&hWaveOut, (WORD) WAVE_MAPPER, (LPWAVEFORMAT) wf,
- 0L, 0L, WAVE_FORMAT_QUERY);
- if (bitsPerSample > 8 && woo == WAVERR_BADFORMAT) {
- audioIs8Bit = TRUE;
- }
-
- /* If our preferred mode (16 bit, 11025 samples/second) isn't
- supported, try falling back to bottom-feeder 8 bit per sample
- mode. */
-
- if ((audioUse8Bit || woo == WAVERR_BADFORMAT) && bitsPerSample > 8) {
- bitsPerSample /= 2;
- sampleAlignment /= 2;
- bytesPerSecond /= 2;
- wf->wf.nAvgBytesPerSec = bytesPerSecond;
- wf->wf.nBlockAlign = sampleAlignment;
- wf->wBitsPerSample = bitsPerSample;
- woo = waveOutOpen(&hWaveOut, (WORD) WAVE_MAPPER, (LPWAVEFORMAT) wf,
- 0L, 0L, WAVE_FORMAT_QUERY);
- }
-
- /* If we've failed to initialise in either 16 or 8 bit mode
- at 8000 samples per second, it's possible the sound card
- doesn't support any sampling mode below the Windows standard
- of 11025 samples per second. Have another go-round and see
- if 11025 works. */
-
- if (woo == WAVERR_BADFORMAT && samplesPerSecond == 8000) {
- samplesPerSecond = 11025;
- bitsPerSample = 16;
- sampleAlignment = bitsPerSample / 8;
- bytesPerSecond = samplesPerSecond * sampleAlignment;
- } else {
- break;
- }
- }
-
- if (woo != 0) {
- char et[MAXERRORLENGTH];
-
- waveOutGetErrorText(woo, et, sizeof et);
- MessageBox(hwnd, et, rstring(IDS_T_WAVE_PLAY_FORMAT_ERR),
- MB_OK | MB_ICONEXCLAMATION);
- GlobalFreePtr(wf);
- return FALSE;
- }
- if ((woo = waveOutOpen(&hWaveOut, (WORD) WAVE_MAPPER,
- (LPWAVEFORMAT) wf, (DWORD) (UINT) hwnd, 0, (DWORD) CALLBACK_WINDOW)) != 0) {
- char et[MAXERRORLENGTH];
-
- /* The next line looks wrong, doesn't it? But I've seen drivers
- for half-duplex sound boards that return NOTSUPPORTED instead
- of ALLOCATED when you try to open input and output at the
- same time. */
-
- if ((woo == MMSYSERR_ALLOCATED || woo == MMSYSERR_NOTSUPPORTED)
- && inputActive) {
- /* Yuck. The fact that we're receiving audio input
- appears to have rendered the audio output port
- busy. Silently sacrifice the packet on the altar
- of this most un-creative sound bobbler. */
- GlobalFreePtr(wf);
- propeller(IDC_PH_INPUT_LOST, ++inputPacketsLost);
- return FALSE;
- }
- waveOutGetErrorText(woo, et, sizeof et);
- MessageBox(hwnd, et, rstring(IDS_T_ERR_OPEN_WAVE_OUTPUT),
- MB_OK | MB_ICONEXCLAMATION);
- GlobalFreePtr(wf);
- return FALSE;
- }
- GlobalFreePtr(wf);
- outputActive = TRUE;
- aboutOutSamples = samplesPerSecond;
- aboutOutBits = bitsPerSample;
- propUpdateAudio();
- }
- }
- return TRUE;
- }
-
- // socketInput -- Process audio packet received on the inbound socket
-
- static VOID socketInput(HWND hwnd, SOCKET sock, SOCKERR serr, SOCKEVENT sevent)
- {
- INT cbRead;
- SOCKADDR_IN addrClient;
- INT cbAddrClient;
- LPCLIENT_DATA pClientData = NULL;
- HWND hwndClient = NULL;
- soundbuf *d = &receivedSoundBuffer;
- static int errorBoxUp = FALSE;
- int hdxPacketLost = FALSE;
-
- #ifdef ZZZ
- if (lwl_t_diactive) {
- lwl_t_siclash = TRUE;
- lwl_t_sic_hwnd = hwnd;
- lwl_t_sic_sock = sock;
- lwl_t_sic_sockerr = serr;
- lwl_t_sic_sockevent = sevent;
- return;
- }
-
- static int lwl_t_siclash;
- static HWND lwl_t_sic_hwnd;
- static SOCKET lwl_t_sic_sock;
- static SOCKERR lwl_t_sic_sockerr;
- static SOCKEVENT lwl_t_sic_sockevent;
- #endif
-
- if (sevent == MODEM_INPUT_EVENT) {
- addrClient.sin_addr.s_addr = 0;
- } else {
- if ((sock != sCommand) || (sevent != FD_READ) || (serr != 0) || errorBoxUp) {
- // Unknown command or unknown event or socket error. Ignore it.
- return;
- }
-
- // We got a packet. Let's see what it tells us to do.
-
- cbAddrClient = sizeof(addrClient);
-
- cbRead = recvfrom(sock, (CHAR FAR *) d, sizeof(soundbuf), 0,
- (SOCKADDR FAR *) &addrClient,
- &cbAddrClient);
- }
- propeller(IDC_PH_PACKETS_RECEIVED, ++packetsReceived);
-
- if (lwl_t_diactive) {
- return;
- }
-
- // Convert packet from network byte order to little-endian
-
- revlong(&(d->compression));
- revlong(&(d->buffer.buffer_len));
-
- // See if a connection window already exists for this host
-
- hwndClient = findClientByHost(&addrClient);
-
- // Create the connection window data if no window exists
-
- if (hwndClient != NULL) {
- pClientData = CLIENTPTR(hwndClient);
- if (pClientData->timeout > 0) {
- pClientData->timeout = 0;
- }
- } else {
- pClientData = (LPCLIENT_DATA) GlobalAllocPtr(GPTR, sizeof(CLIENT_DATA));
- if (pClientData != NULL) {
- _fmemset(pClientData, 0, sizeof(CLIENT_DATA));
- pClientData->dwType = WINDOW_TYPE_CLIENT;
- pClientData->wantsInput = FALSE;
- pClientData->broadcastBeginTime = GetTickCount();
- pClientData->broadcastEnd = FALSE;
- pClientData->state = Embryonic;
- pClientData->sReply = INVALID_SOCKET;
- pClientData->timeout = 0;
- pClientData->inetSock = addrClient;
- pClientData->modemConnection = addrClient.sin_addr.s_addr == 0;
- pClientData->hFile = HFILE_ERROR;
- pClientData->szFile[0] = '\0';
- pClientData->face_stat = FSinit;
- //pClientData->face_stat = -1;
- pClientData->face_bmp = NULL;
- if (!pClientData->modemConnection) {
- /* Set host only on socket connections. Leave dial string
- blank for remote-initiated modem connections. */
- pClientData->szHost[0] = '(';
- _fstrcpy(pClientData->szHost + 1, d->sendinghost);
- _fstrcat(pClientData->szHost, " ");
- _fstrcat(pClientData->szHost, inet_ntoa(pClientData->inetSock.sin_addr));
- _fstrcat(pClientData->szHost, ")");
- }
- } else {
- return; // What'cha gonna do when it fails on you ?
- }
- }
-
- /* If this is a face data request packet, hand it off
- to the face file retriever to to be filled with
- appropriate data and return it to the requestor.
- Note that we do this before attempting to acquire audio
- output. This means that half duplex does not prevent our
- responding to a face request whilst transmitting. */
-
- if ((pClientData->state != Embryonic) &&
- ((d->compression & (fFaceData | faceRequest)) ==
- (fFaceData | faceRequest))) {
- int l;
-
- processFaceRequest(d);
- l = (int) d->buffer.buffer_len;
- revlong(&(d->compression));
- revlong(&(d->buffer.buffer_len));
- if (!useSendNotSendto) {
- int stat;
-
- stat = sendto(pClientData->sReply, (LPSTR) d,
- l + (sizeof(soundbuf) - BUFL),
- 0, (LPSOCKADDR) &(pClientData->name), sizeof pClientData->name);
- if (stat < 0) {
- useSendNotSendto = TRUE;
- if (hDlgPropeller != NULL) {
- SetDlgItemText(hDlgPropeller, IDC_PH_SENDTO, rstring(IDS_T_SEND));
- }
- }
- }
- if (useSendNotSendto) {
- send(pClientData->sReply, (LPSTR) d, l + (sizeof(soundbuf) - BUFL), 0);
- }
- propeller(IDC_PH_PACKETS_SENT, ++packetsSent);
- return;
- }
-
- /* If this is a face data reply, pass it to the mechanism
- that's assembling the face in memory. */
-
- if ((d->compression & fFaceData) && (hwndClient != NULL) && (pClientData != NULL)) {
- processFaceData(hwndClient, pClientData, d);
- return;
- }
-
- // Grab the audio device if we don't already have it
-
- outputTimeout = 0; // Reset release output timeout
- if (!obtainOutput(hwnd)) {
- hdxPacketLost = TRUE;
- /* If we're broadcasting, we ignore the failure to obtain
- output due to half duplex hardware. This allows remote
- users to blip us to subscribe to the broadcast. */
- if (!broadcasting) {
- goto FatalAudioExit;
- }
- }
-
- if (pClientData == NULL) {
- goto FatalExit;
- }
-
- if (pClientData->state == Embryonic) {
-
- /* If our main window is iconic and we're establishing a
- new connection, restore the window so the user can see
- who's connecting. "Look who's talking!" */
-
- if (IsIconic(hwnd) && lookWho_sTalking) {
- ShowWindow(hwnd, SW_SHOWNORMAL);
- }
- // Create a new connection child window
- hwndClient = createNewConnection(pClientData);
- }
-
- if (hwndClient != NULL) {
-
- pClientData->cbReceived += d->buffer.buffer_len;
- if (pClientData->timeout > 0) {
- pClientData->timeout = 0;
- }
-
- /* If loopback is requested, bung it right back to the sender
- remembering, of course, first to clear the loopback bit. */
-
- if (d->compression & fLoopBack) {
- d->compression ^= fLoopBack;
- revlong(&(d->compression)); // *sigh*
- revlong(&(d->buffer.buffer_len));
- if (!useSendNotSendto) {
- int stat;
-
- stat = sendto(pClientData->sReply, (LPSTR) d, cbRead,
- 0, (LPSOCKADDR) &(pClientData->name), sizeof pClientData->name);
- if (stat < 0) {
- useSendNotSendto = TRUE;
- if (hDlgPropeller != NULL) {
- SetDlgItemText(hDlgPropeller, IDC_PH_SENDTO, rstring(IDS_T_SEND));
- }
- }
- }
- if (useSendNotSendto) {
- send(pClientData->sReply, (LPSTR) d, cbRead, 0);
- }
- revlong(&(d->compression));
- revlong(&(d->buffer.buffer_len));
- propeller(IDC_PH_PACKETS_SENT, ++packetsSent);
- }
-
- #ifdef SHOW_RECEIVED_IN_WINDOW
- /* It's ugly to scribble directly into the client's
- window here, but it's enormously faster than sending
- him a WM_PAINT and forcing him to redraw everything. */
-
- if (!IsIconic(hwndClient)) {
- HDC hdc = GetDC(hwndClient);
-
- WinPrintf(hdc, 4, 20, Format(28), pClientData->cbReceived);
- ReleaseDC(hwndClient, hdc);
- }
- #endif
-
- /* If we're broadcasting, allow a site to drop the broadcast
- by blipping the mike BroadcastUnsubscribe seconds or later
- after the initial subscription. (The delay prevents multiple
- packets from the original subscribe or unsubscribe request
- from flipping the subscription back and forth.) */
-
- if (broadcasting) {
- if ((!pClientData->broadcastEnd) &&
- ((GetTickCount() - pClientData->broadcastBeginTime) >
- (BroadcastUnsubscribe * 1000L))) {
- pClientData->broadcastEnd = TRUE;
- pClientData->broadcastBeginTime = GetTickCount();
- }
- }
-
- /* If this is a PGP-encrypted session key, determine if
- we need to decrypt it and put it into effect. We disable
- this during a broadcast so users can't bring us to a
- screeching halt by sending a PGP key request. */
-
- if ((d->compression & fKeyPGP) && !broadcasting) {
- pgpSetSessionKey(hwndClient, pClientData, d);
- } else {
-
- /* If the sending host offers us a face image and
- we haven't already undertaken its retrieval, start
- up the process to fetch it in the background. */
-
- if (faceShow && (d->compression & fFaceOffer) &&
- (pClientData->face_stat == FSinit)) {
- connFetchFace(hwndClient, pClientData);
- }
-
- // Okay, now we're ready to play the sound buffer
-
- if (!hdxPacketLost) {
- pClientData->state = PlayingReceivedAudio;
- playSound(hwndClient, pClientData, d, bitsPerSample, samplesPerSecond);
- }
- }
- return;
- }
-
- // Unable to create connection window
-
- if (pClientData != NULL) {
- GlobalFreePtr(pClientData);
- }
-
- FatalExit:
- if (hwndClient != NULL) {
- FORWARD_WM_MDIDESTROY(hwndMDIClient, hwndClient, SendMessage);
- }
-
- FatalAudioExit:
- errorBoxUp = FALSE;
- }
-
- // MODEMINPUT -- Finite state machine for processing modem input
-
- static int modemInputState = 0;
-
- static void modemInput(HWND hwnd)
- {
- char modembuf[256];
- int l;
- char *cp = modembuf;
- static LPSTR op;
- static short len, ilen;
- static unsigned short bcrc;
- COMSTAT cs;
-
- int err = GetCommError(modemHandle, &cs);
- if (err != 0) {
- MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(16), err);
- errorRant(hwnd);
- }
- l = ReadComm(modemHandle, modembuf, sizeof modembuf);
- err = GetCommError(modemHandle, &cs);
- if (err != 0) {
- MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(17), err);
- errorRant(hwnd);
- return;
- }
-
- while (l-- > 0) {
- char ch = *cp++;
-
- switch (modemInputState) {
- case 0:
- if (ch == 1) {
- if (modemSb == NULL) {
- modemSb = (LPSTR) GlobalAllocPtr(GPTR, sizeof(soundbuf) + 12);
- if (modemSb == NULL) {
- return;
- }
- }
- modemInputState++;
- op = (LPSTR) modemSb;
- break;
- }
- continue;
-
- case 1:
- case 2:
- case 3:
- if (ch == (modemInputState + 1)) {
- modemInputState++;
- } else {
- modemInputState = 0;
- continue;
- }
- break;
-
- case 4:
- case 5:
- case 6:
- modemInputState++;
- break;
-
- case 7:
- /* Look at the length specification and its checksum
- inverted copy and proceed only if it's plausible. */
- len = *((short FAR *) (op - 3));
- revshort(&len);
- ilen = (((unsigned short) op[-1]) << 8) | ((unsigned char) ch);
- if (len < (sizeof(soundbuf) - BUFL) ||
- len > sizeof(soundbuf) || len != ~ilen) {
- modemInputState = 0;
- continue;
- }
- ilen = len;
- modemInputState++;
- break;
-
- // Receiving sound buffer
-
- case 8:
- if (--len <= 0) {
- modemInputState++;
- }
- break;
-
- // Receiving two CRC bytes
-
- case 9:
- case 10:
- modemInputState++;
- if (modemInputState < 11) {
- break;
- }
- // Wheeee!!! Note fall-through.
-
- // Complete buffer received
-
- case 11:
- modemInputState = 0; // Reset state machine
- bcrc = crc(modemSb, ilen + 4 + 2 * sizeof(unsigned short));
- if (((bcrc >> 8) != (unsigned char) op[-1]) || ((bcrc & 0xFF) != (unsigned char) ch)) {
- /* CRC error. Probably should have options in the
- modem options dialogue to discard CRC error buffers
- or try to play them regardless. */
- MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(18));
- errorRant(hwnd);
- }
- _fmemcpy(&receivedSoundBuffer,
- modemSb + 4 + 2 * sizeof(unsigned short), ilen);
- socketInput(hwnd, 0, 0, MODEM_INPUT_EVENT);
- continue;
- }
- *op++ = ch;
- }
- GetCommEventMask(modemHandle, EV_RXCHAR);
- }
-
- // Frame_WndProc -- Main frame window procedure
-
- LRESULT CALLBACK Frame_WndProc(HWND hwnd, UINT nMessage, WPARAM wParam,
- LPARAM lParam)
- {
- int i;
- char conn[12];
- char *cg;
-
- switch (nMessage) {
-
- HANDLE_MSG(hwnd, WM_COMMAND, onCommand);
- HANDLE_MSG(hwnd, WM_CREATE, onCreate);
- HANDLE_MSG(hwnd, WM_SOCKET_SELECT, socketInput);
-
- case WM_COMMNOTIFY:
- if (modemHandle != -1) {
- switch (LOWORD(lParam)) {
- case CN_RECEIVE:
- modemInput(hwnd);
- break;
-
- case CN_TRANSMIT:
- GetCommEventMask(modemHandle, EV_TXEMPTY);
- break;
-
- case CN_EVENT:
- {
- UINT stat = GetCommEventMask(modemHandle, CN_EVENT);
- COMSTAT lps;
- int err;
-
- if (stat == EV_ERR) {
- err = GetCommError(modemHandle, &lps);
- // if (err & (CE_RXOVER | CE_OVERRUN)) {
- // FlushComm(modemHandle, 1);
- // }
- // FlushComm(modemHandle, 0);
- /*
- if (err == CE_OVERRUN) {
- return 0; // Nothing we can do about it!
- }
- */
- if (err != 0) {
- MsgBox(NULL, MB_ICONSTOP | MB_OK,
- Format(19), err);
- errorRant(hwnd);
- }
- }
- stat = 0;
- }
- return 0;
- }
- }
- break;
-
- case WM_CLOSE:
- terminateWaveInput(); // Terminate wave input if active
- if (outputActive) {
- V waveOutReset(hWaveOut);
- V waveOutClose(hWaveOut);
- outputActive = FALSE;
- }
- DestroyWindow(hwnd);
- return 0;
-
- case WM_DESTROY:
- KillTimer(hwnd, FRAME_TIMER_ID); // Kill main timeout timer
- if (pfnPropeller != NULL) {
- FreeProcInstance(pfnPropeller); // Release propeller-head procedure
- }
- if (pfnAnswer != NULL) {
- FreeProcInstance(pfnAnswer);// Release answering machine procedure
- }
- gsm_destroy(gsmh); // Shut down GSM decoding
- terminateWaveInput(); // Terminate wave input if active
- answerClose(); // Close the answering machine
- closeFaceFile(); // Close face image file
- closeModem(hwnd); // Modem α dodo
- if (modemSb != NULL) {
- GlobalFreePtr(modemSb); // Release modem buffer
- }
- waveOutShutdown(); // Close wave audio output
- multicastJoin(NULL, FALSE); // Drop all multicast group memberships
-
- // If an incomplete LWL periodic update is pending, terminate it
-
- if (lwlsock != INVALID_SOCKET) {
- shutdown(lwlsock, 2);
- closesocket(lwlsock);
- }
- if (lwl_t_published) {
- sendLwlMessage(hwnd, TRUE); // Send BYE message to Look Who's Listening
- }
- SetCursor(NULL); // Make sure we don't destroy current cursor
- if (phoneCursor != NULL) {
- DestroyCursor(phoneCursor); // Release custom cursors
- }
- if (earCursor != NULL) {
- DestroyCursor(earCursor);
- }
-
- {
- char pfn[80];
-
- _fstrcpy(pfn, rstring(IDS_PF_PROFILE_FILE));
-
- // Save remembered connections
-
- wsprintf(conn, Format(5), rememberedConnections);
- cg = rstring(IDS_PF_CONNECTIONS);
- WritePrivateProfileString(cg, rstring(IDS_PF_CONNCOUNT),
- conn, pfn);
- for (i = 0; i < rememberedConnections; i++) {
-
- wsprintf(conn, Format(2), i + 1);
- WritePrivateProfileString(cg, conn,
- rememberedConnection[i], pfn);
- GlobalFreePtr(rememberedConnection[i]);
- }
-
- // Save multicast group memberships
-
- wsprintf(conn, Format(5), multiMemberships);
- /* Must re-fetch IDS_PF_MULTIGROUPS each time since there can be
- sufficient multicast subscriptions to wrap rstring() circular
- buffer. */
- WritePrivateProfileString(rstring(IDS_PF_MULTIGROUPS),
- rstring(IDS_PF_CONNCOUNT), conn, pfn);
- for (i = 0; i < multiMemberships; i++) {
-
- wsprintf(conn, Format(3), i + 1);
- WritePrivateProfileString(rstring(IDS_PF_MULTIGROUPS), conn,
- inet_ntoa(multiAddr[i]), pfn);
- wsprintf(conn, Format(4), i + 1);
- WritePrivateProfileString(rstring(IDS_PF_MULTIGROUPS), conn,
- multiName[i] == NULL ? "" : multiName[i],
- pfn);
- if (multiName[i] != NULL) {
- GlobalFreePtr(multiName[i]);
- }
- }
- WritePrivateProfileString(rstring(IDS_PF_MULTIGROUPS), rstring(IDS_PF_LOOPBACK),
- multiLoop ? kS1 : kS0, pfn);
-
- // Save compression modes
-
- #define BoolProfile(var, section, itemname, defval) WritePrivateProfileString(section, itemname, var ? kS1 : kS0, pfn)
- cg = rstring(IDS_PF_COMPRESSION);
- BoolProfile(compression, cg, rstring(IDS_PF_COMP_SIMPLE), FALSE);
- BoolProfile(gsmcompress, cg, rstring(IDS_PF_COMP_GSM), TRUE);
- BoolProfile(adpcmcompress, cg, rstring(IDS_PF_COMP_ADPCM), FALSE);
- BoolProfile(lpccompress, cg, rstring(IDS_PF_COMP_LPC), FALSE);
-
- // Save modem configuration
-
- cg = rstring(IDS_PF_MODEM);
- BoolProfile(modemEnable, cg, rstring(IDS_PF_ENABLE), FALSE);
- WritePrivateProfileString(cg, rstring(IDS_PF_PORT),
- commport, pfn);
- WritePrivateProfileString(cg, rstring(IDS_PF_BAUDRATE),
- baudrate, pfn);
- WritePrivateProfileString(cg, rstring(IDS_PF_MODEM_INIT_STRING),
- modemInitString, pfn);
- BoolProfile(modemShowRant, cg, rstring(IDS_PF_SHOW_RANT), TRUE);
-
- // Save answering machine settings
-
- cg = rstring(IDS_PF_ANSWER);
- WritePrivateProfileString(cg, rstring(IDS_PF_FILE_NAME),
- answerFileName, pfn);
- BoolProfile(answerRecord, cg, rstring(IDS_PF_RECORD_MESSAGES), FALSE);
-
- // Restore in your face settings
-
- WritePrivateProfileString(rstring(IDS_PF_FACE), rstring(IDS_PF_FILE_NAME),
- faceFileName, pfn);
- BoolProfile(faceShow, rstring(IDS_PF_FACE), rstring(IDS_PF_SHOW_FACES), TRUE);
-
- // Save preferences
-
- WritePrivateProfileString(rstring(IDS_PF_RING),
- rstring(IDS_PF_FILE_NAME), ringFileName, pfn);
- BoolProfile(lookWho_sTalking, rstring(IDS_PF_PREFERENCES), rstring(IDS_PF_LOOKWHO), FALSE);
-
- // Save Look Who's Listening parameters
-
- WritePrivateProfileString(rstring(IDS_PF_LWL_TELL),
- rstring(IDS_PF_SERVER), lwl_s_server, pfn);
- WritePrivateProfileString(rstring(IDS_PF_LWL_TELL),
- rstring(IDS_PF_EMAIL), lwl_s_email, pfn);
- WritePrivateProfileString(rstring(IDS_PF_LWL_TELL),
- rstring(IDS_PF_FULLNAME), lwl_s_fullname, pfn);
- WritePrivateProfileString(rstring(IDS_PF_LWL_TELL),
- rstring(IDS_PF_PHONE), lwl_s_phone, pfn);
- WritePrivateProfileString(rstring(IDS_PF_LWL_TELL),
- rstring(IDS_PF_LOCATION), lwl_s_location, pfn);
- BoolProfile(lwl_s_publish, rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_PUBLISH), FALSE);
- BoolProfile(lwl_s_exact, rstring(IDS_PF_LWL_TELL), rstring(IDS_PF_EXACT), FALSE);
-
- WritePrivateProfileString(rstring(IDS_PF_LWL_ASK),
- rstring(IDS_PF_SERVER), lwl_a_server, pfn);
- BoolProfile(lwl_a_exact, rstring(IDS_PF_LWL_ASK), rstring(IDS_PF_EXACT), FALSE);
-
- // Save workarounds
-
- cg = rstring(IDS_PF_WORKAROUNDS);
- BoolProfile(alwaysBindSocket, cg, rstring(IDS_PF_ALWAYS_BIND), FALSE);
- BoolProfile(waNetNoConnect, cg, rstring(IDS_PF_NET_NO_CONNECT), FALSE);
- BoolProfile(waNetUseSend, cg, rstring(IDS_PF_NET_USE_SEND), FALSE);
- BoolProfile(waNetMultiTTLisChar, cg, rstring(IDS_PF_MULTICAST_CHAR_ARG), FALSE);
- BoolProfile(waAudioHalf, cg, rstring(IDS_PF_AUDIO_HALF_DUPLEX), FALSE);
- BoolProfile(waAudio11025, cg, rstring(IDS_PF_AUDIO_SAMPLE_11025), FALSE);
- #undef BoolProfile
- }
-
- // Disconnect from the sockets library before terminating
-
- WSACleanup();
-
- // If we launched help, shut it down now
-
- if (holped) {
- WinHelp(hwnd, rstring(IDS_HELPFILE), HELP_QUIT, 0L);
- }
- PostQuitMessage(0);
- return 0L;
-
- case WM_DROPFILES:
- {
- char dropConn[MAX_PATH];
- UINT nfiles = DragQueryFile((HDROP) wParam, 0xFFFF, dropConn, sizeof dropConn),
- fn;
-
- for (fn = 0; fn < nfiles; fn++) {
- DragQueryFile((HDROP) wParam, fn, dropConn, sizeof dropConn);
- newConnection(hwnd, dropConn, NULL);
- }
- DragFinish((HDROP) wParam);
- }
- break;
-
- #ifdef ZZZ
- case WM_QUERYNEWPALETTE:
- {
- HWND hActive;
-
- hActive = (HWND) LOWORD(SendMessage(hwndMDIClient, WM_MDIGETACTIVE, 0, 0L));
-
- if (hActive != NULL) {
- return SendMessage(hActive, WM_QUERYNEWPALETTE, hwnd, 0L);
- }
-
- return FALSE;
- }
- #endif
-
- case WM_INITMENU:
- { HMENU menu = (HMENU) wParam;
- int connActive = FALSE;
- HWND hWndClient = getActiveConnection();
- LPCLIENT_DATA pClientData;
- HMENU connect;
-
- /* Tack recent remembered connections to the end of
- the "Connect" menu. */
-
- connect = GetSubMenu(GetMenu(hwnd), 0);
- if (connect != NULL) {
- int i;
-
- for (i = 0; i <= REMEMBER_CONNECTIONS; i++) {
- DeleteMenu(connect, IDM_CUSTOM + i, MF_BYCOMMAND);
- }
- if (rememberedConnections > 0) {
- AppendMenu(connect, MF_SEPARATOR, IDM_CUSTOM, NULL);
- for (i = 0; i < rememberedConnections; i++) {
- AppendMenu(connect, MF_STRING, IDM_CUSTOM + i + 1,
- rememberedConnection[i]);
- }
- }
- }
- if (hWndClient != NULL) {
- connActive = TRUE;
- pClientData = CLIENTPTR(hWndClient);
- }
- #define Enable(item, condition) EnableMenuItem(menu, (item), MF_BYCOMMAND | \
- ((condition) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
- #define Checker(item, value) CheckMenuItem(menu, (item), MF_BYCOMMAND | \
- ((value) ? MF_CHECKED : MF_UNCHECKED))
-
- Enable(IDM_CONN_PROPERTIES, connActive);
- Enable(IDM_CONN_RING, connActive && pClientData->hFile == HFILE_ERROR &&
- pClientData->mmioHandle == NULL);
- Enable(IDM_SEND_SOUND_FILE, connActive && pClientData->hFile == HFILE_ERROR &&
- pClientData->mmioHandle == NULL);
- Enable(IDM_DISCONNECT, connActive);
- Enable(IDM_CONN_SAVE, connActive && pClientData->connectionFileName[0]);
- Enable(IDM_CONN_SAVE_AS, connActive);
- Enable(IDM_CO_RECORD, answerEnabled());
- Checker(IDM_CO_RECORD, answerEnabled() && answerRecord);
- Checker(IDM_CONN_BROADCAST, broadcasting);
- Checker(IDM_OPT_LOOK_WHO, lookWho_sTalking);
-
- // Workarounds can be changed only when no connection active
-
- #define WorkA(item, value) Enable(item, !connActive); Checker(item, value)
- WorkA(IDM_WORKA_BIND, alwaysBindSocket);
- WorkA(IDM_WORKA_NOCONNECT, waNetNoConnect);
- WorkA(IDM_WORKA_USE_SEND, waNetUseSend);
- WorkA(IDM_WORKA_TTLCHAR, waNetMultiTTLisChar);
- WorkA(IDM_WORKA_HALF_DUPLEX, waAudioHalf);
- WorkA(IDM_WORKA_SAMPLE_11025, waAudio11025);
- #undef WorkA
-
- // Compression can be changed only when input is idle
-
- Enable(IDM_COMP_2X, !inputActive);
- Checker(IDM_COMP_2X, compression);
- Enable(IDM_COMP_GSM, !inputActive);
- Checker(IDM_COMP_GSM, gsmcompress);
- Enable(IDM_COMP_ADPCM, !inputActive);
- Checker(IDM_COMP_ADPCM, adpcmcompress);
- Enable(IDM_COMP_LPC, !inputActive);
- Checker(IDM_COMP_LPC, lpccompress);
-
- // Audio must be idle to change 8/16 bit mode
-
- Enable(IDM_OPT_8BIT, !audioIs8Bit && !inputActive && !outputActive);
- Checker(IDM_OPT_8BIT, (audioUse8Bit || audioIs8Bit));
-
- /* Can't access LWL server when input active (because it
- could lead to a reentrant call to WINSOCK. */
-
- Enable(IDM_DIR_LISTING, !inputActive);
- Enable(IDM_DIR_SEARCH, !inputActive);
-
- // Can't change modem configuration while modem session active
-
- Enable(IDM_OPT_MODEM, modemSessions == 0);
- if (connActive) {
- ModifyMenu(GetSubMenu(menu, 0), IDM_SEND_SOUND_FILE,
- MF_BYCOMMAND | MF_STRING | MF_ENABLED, IDM_SEND_SOUND_FILE,
- (pClientData->hFile == HFILE_ERROR &&
- pClientData->mmioHandle == NULL) ? rstring(IDS_T_SEND_SOUND_MENU) :
- rstring(IDS_T_STOP_SOUND_MENU));
- }
- Enable(IDM_PROPELLER_HEAD, hDlgPropeller == NULL);
- Enable(IDM_CO_REPONDEUR, hDlgAnswer == NULL);
- }
- #undef Checker
- #undef Enable
- break;
-
- case WM_SOCKET_LWL:
- if (WSAGETSELECTEVENT(lParam) == FD_WRITE) {
- if (send(lwlsock, (char *) sdes, sdesl, 0) < 0) {
- int serr = WSAGetLastError();
-
- MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(56),
- serr, SockerrToString(serr));
- lwl_t_published = FALSE;
- }
- closesocket(lwlsock);
- lwlsock = INVALID_SOCKET;
- }
- break;
-
- case WM_TIMER:
- {
- HWND hwndChild;
-
- hwndChild = GetWindow(hwndMDIClient, GW_CHILD);
-
- while (hwndChild != NULL) {
- if (GetWindow(hwndChild, GW_OWNER) == NULL) {
- FORWARD_WM_TIMER(hwndChild, wParam, PostMessage);
- }
-
- hwndChild = GetWindow(hwndChild, GW_HWNDNEXT);
- }
-
- /* Now this is thoroughly idiotic place to initialise
- the modem at start-up time, isn't it? Why do it
- here? Because if you do it at the logical place, in
- WM_CREATE, it doesn't work. No error return anywhere
- along the way, of course--this is Windows, after all,
- but the port is as dead as the weight of Microsoft
- on the struggling developer. */
-
- if (modemEnable && modemHandle == -1) {
- if (!openModem(hwnd)) {
- modemEnable = FALSE;
- }
- }
- }
-
- /* If TIMEOUT_AUDIO_OUTPUT seconds have elapsed since we
- sent the last buffer to audio output, shut down audio
- output so as to make it available to other applications. */
-
- if (outputActive && outputPending == 0 &&
- ++outputTimeout >= TIMEOUT_AUDIO_OUTPUT) {
- answerSync();
- waveOutShutdown();
- }
-
- /* If we're publishing Look Who's Listening information and
- we're approaching the timeout interval for the server,
- re-send our information to avoid being timed out. */
-
- if (lwl_t_published && !lwl_t_diactive) {
- if (--lwl_t_resend <= 0) {
- lwl_t_resend = TIMEOUT_RESEND_LWL; // Reset resend timer
- #ifdef BLOCK_SOCK
- if ((lwl_t_published = sendLwlMessage(hwnd, FALSE)) != FALSE) {
- lwl_t_resend = TIMEOUT_RESEND_LWL; // Set resend timer
- }
- #else
-
- /* We want to do this update in asynchronous mode so
- as not to interfere with sound traffic. Create the
- socket, place it into async mode, and initiate the
- connection. We'll proceed with the subsequent steps
- when we receive notification of the connection.
-
- First of all, we want to be sure the last periodic
- update isn't still pending. If so, that indicates
- things are hung up, so we'll disable LWL for the
- test of this session. */
-
- if (lwlsock != INVALID_SOCKET) {
- shutdown(lwlsock, 2);
- closesocket(lwlsock);
- lwlsock = INVALID_SOCKET;
- lwl_t_published = FALSE;
- MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(58));
- } else {
- lwlsock = socket(AF_INET, SOCK_STREAM, 0);
- if (lwlsock == INVALID_SOCKET) {
- int serr = WSAGetLastError();
-
- MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(54),
- serr, SockerrToString(serr));
- lwl_t_published = FALSE;
- } else {
- int ling = TRUE;
-
- WSAAsyncSelect(lwlsock, hwnd, WM_SOCKET_LWL, FD_WRITE | FD_CLOSE);
- setsockopt(lwlsock, SOL_SOCKET, SO_DONTLINGER, (char *) &ling, sizeof ling);
- if (connect(lwlsock, (struct sockaddr *) &(lookhost), sizeof lookhost) == SOCKET_ERROR) {
- int serr = WSAGetLastError();
-
- if (serr != WSAEWOULDBLOCK) {
- MsgBox(hwnd, MB_ICONSTOP | MB_OK, Format(56),
- serr, SockerrToString(serr));
- closesocket(lwlsock);
- lwlsock = INVALID_SOCKET;
- lwl_t_published = FALSE;
- }
- }
- }
- }
- #endif
- }
- }
- break;
-
- /* Input sound buffer received. Pass it on to the output
- handler of every client window that presently says it
- wants input. */
-
- case MM_WIM_DATA:
- {
- LPWAVEHDR isb;
- HWND hwndClient = GetWindow(hwndMDIClient, GW_CHILD);
-
- if (!inputTerm) {
- int firstTime = TRUE;
-
- /* One little subtlety. Since we allow the user to
- change compression modes on the fly, the buffer that
- just arrived may have been filled based on out of
- date compression modes. In particular, if it's longer
- than we currently expect, it could frag the network.
- If this is the case, chop the extra samples off the
- end of the buffer. This causes momentary loss of sound,
- but that's a lot better than the dreaded "Cannot write to
- socket" network error. There's no problem processing a
- buffer shorter than expected, except a possible momentary
- click in GSM encoding. */
-
- isb = (LPWAVEHDR) lParam;
- if (isb->dwBytesRecorded > (DWORD) currentInputLength) {
- isb->dwBytesRecorded = currentInputLength;
- }
-
- while (hwndClient != NULL) {
- if ((WNDPROC) GetWindowLong(hwndClient, GWL_WNDPROC) == ((WNDPROC) connectWndProc)) {
- LPCLIENT_DATA pClientData = CLIENTPTR(hwndClient);
-
- if ((pClientData != NULL) &&
- IS_CLIENT_WINDOW(hwndClient) &&
- (pClientData->wantsInput || broadcasting)) {
-
- #ifdef SHOW_MIM
- if (!IsIconic(hwnd)) {
- HDC hdc = GetDC(hwnd);
- static long reccount = 0;
-
- reccount += isb->dwBytesRecorded;
- WinPrintf(hdc, 6, 1, "Input: %lu", reccount);
- ReleaseDC(hwnd, hdc);
- }
- #endif
- if (firstTime) {
- createSoundBuffer(isb->lpData,
- (WORD) isb->dwBytesRecorded,
- audioChannels, samplesPerSecond,
- bytesPerSecond, sampleAlignment);
- firstTime = FALSE;
- }
- shipSoundBuffer(hwndClient, pClientData);
- }
- }
- hwndClient = GetWindow(hwndClient, GW_HWNDNEXT);
- }
- isb->dwBufferLength = currentInputLength;
- waveInAddBuffer(hWaveIn, isb, sizeof(WAVEHDR));
- }
- }
- break;
-
- // Output sound buffer complete
-
- case MM_WOM_DONE:
- {
- LPWAVEHDR waveHdr = (LPWAVEHDR) lParam;
- outputPending--;
- if (hDlgPropeller != NULL) {
- char s[80];
-
- wsprintf(s, outputPending == 0 ? Format(6) : Format(7),
- outputPending);
- SetDlgItemText(hDlgPropeller, IDC_PH_AUDIO_OUT_QUEUE, s);
- }
- #ifdef DEBUG_OUTPUT_RELEASE
- if (!IsIconic(hwnd)) {
- HDC hdc = GetDC(hwnd);
- static long bf = 0;
-
- bf += waveHdr->dwBufferLength / 2;
- WinPrintf(hdc, 3, 30, " Freed: %lu Pending: %lu", bf, outputPending);
- ReleaseDC(hwnd, hdc);
- }
- #endif
- waveOutUnprepareHeader(hWaveOut, waveHdr, sizeof(WAVEHDR));
- GlobalFreePtr(waveHdr->lpData);
- GlobalFreePtr(waveHdr);
- if ((halfDuplexTransition || outputInShutdown) &&
- (outputPending == 0)) {
- waveOutClose(hWaveOut);
- outputActive = FALSE;
- if (!outputInShutdown && halfDuplexTransition) {
- V startWaveInput(hwnd);
- }
- halfDuplexTransition = outputInShutdown = FALSE;
- propUpdateAudio();
- }
- }
- break;
-
- default:
-
- // Check for help button in a file open/save dialogue we own
-
- if (nMessage == fileOpenHelpButton && fileHelpKey != NULL) {
- WinHelp(hwnd, rstring(IDS_HELPFILE), HELP_KEY,
- ((DWORD) (LPSTR) fileHelpKey));
- holped = TRUE;
- }
- break;
- }
-
- return DefFrameProc(hwnd, hwndMDIClient, nMessage, wParam, lParam);
-
- }
-
-